Files
edgetx-gx12/radio/src/targets/9x/lcd_st7920_driver.cpp
T
3djcandBertrand Songis fa951acf40 Review line ending handling (#4820)
* New line end handling rules

* Normalize all the line endings
2017-04-19 10:54:43 +02:00

138 lines
4.2 KiB
C++

/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
void lcdSendCtl(uint8_t val)
{
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
PORTA_LCD_DAT = val;
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
}
const static pm_uchar lcdInitSequence[] PROGMEM =
{
0x30, // Set 8-bit interface
0x36, // Repeat with graphics bit set to ON
0x0C, // Display ON, cursor and blink OFF
0x01, // Clear display, reset address
0x06 // Display ON, no cursor
};
void lcdInit()
{
LCD_LOCK();
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); //LCD reset
_delay_us(2);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //LCD normal operation
_delay_ms(40);
for (uint8_t i=0; i<DIM(lcdInitSequence); i++) {
lcdSendCtl(pgm_read_byte(&lcdInitSequence[i])) ;
_delay_us(80);
}
g_eeGeneral.contrast = 0x22;
LCD_UNLOCK();
}
void lcdSetRefVolt(uint8_t val)
{
}
uint8_t lcdRefresh_ST7920(uint8_t full)
{
LCD_LOCK();
static uint8_t state;
uint8_t yst;
uint8_t yend;
uint8_t y_table[6]={0,13,26,39,52,64};
uint8_t x_addr = 0;
uint8_t y_addr = 0;
uint16_t line_offset = 0;
uint8_t col_offset = 0;
uint8_t bit_count = 0;
uint8_t result;
uint8_t *p;
if(full!=0){
yst=0;
yend=64;
state=0;
}
else{ //Since writing to ST7920 is too slow we need to split it to five bands
yst=y_table[state];
yend=y_table[state+1];
if (state==4){
state=0;
}
else{
state++;
}
}
for (uint8_t y=yst; y<yend; y++) {
x_addr = 0;
//Convert coordinates to weirdly-arranged 128x64 screen (the ST7920 is mapped for 256x32 displays)
if (y > 31) {
y_addr = y - 32; //Because there are only 31 addressable lines in the ST7920
x_addr += 8; //so we overflow x (7 visible bytes per line) to reach the bottom half
}
else {
y_addr = y;
}
lcdSendCtl( 0x80 | y_addr ); //Set Vertical Address
_delay_us(49);
lcdSendCtl( 0x80 | x_addr ); //Set Horizontal Address
_delay_us(49);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0); //HIGH RS and LOW RW will put the LCD to
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW); //Write data register mode
bit_count = y & 0x07; //Count from 0 bis 7 -> 0=0, 1=1..7=7, 8=0, 9=1...
col_offset = 1 << bit_count; //Build a value for a AND operation with the vorrect bitposition
line_offset = ( y / 8 ) * 128; //On the ST7565 there are 8 lines with each 128 bytes width
for (coord_t x=0; x<16; x++) { //Walk through 16 bytes form left to right (128 Pixel)
p = displayBuf + line_offset + ( x * 8 ); //Calculate the position of the first byte im array
// adressing the bytes sequential and set the bits at the correct position merging them with an OR operation to get all bits in one byte
// the position of the LSB is the right-most position of the byte to the ST7920
result = ((*p++ & col_offset)!=0?0x80:0);
result |= ((*p++ & col_offset)!=0?0x40:0);
result |= ((*p++ & col_offset)!=0?0x20:0);
result |= ((*p++ & col_offset)!=0?0x10:0);
result |= ((*p++ & col_offset)!=0?0x08:0);
result |= ((*p++ & col_offset)!=0?0x04:0);
result |= ((*p++ & col_offset) !=0?0x02:0);
result |= ((*p++ & col_offset)!=0?0x01:0);
PORTA_LCD_DAT = result;
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
_delay_us(8);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
_delay_us(49);
}
}
LCD_UNLOCK();
return state;
}
void lcdRefresh()
{
lcdRefresh_ST7920(1);
}