ST7920 support added for 9x and M2560 boards

Merge of olterion ST7920 driver, thanks :)
Draft... please check !
This commit is contained in:
JivaroFAD
2015-05-17 20:26:41 +02:00
parent b5a47a9f57
commit 744c797e30
2 changed files with 113 additions and 52 deletions
+13 -7
View File
@@ -57,6 +57,10 @@ PCB = 9X
# PCB revision
PCBREV =
# LCD
# Values: DEFAULT, ST7565P, ST7565R, ERC12864FSF, ST7920
LCD = DEFAULT
# Enable JETI-Telemetry or FrSky Telemetry reception on UART0
# For this option you need to modify your hardware!
# More information at [insertURLhere]
@@ -681,13 +685,7 @@ ifeq ($(PCB), MEGA2560)
BITMAPS += bitmaps/9X/splash.lbm bitmaps/9X/asterisk.lbm bitmaps/9X/about.lbm
GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_diagkeys.cpp gui/$(GUIDIRECTORY)/menu_general_diaganas.cpp
# LCD driver
# Values: ST7565P(default), ST7565R
LCD = ST7565P
ifeq ($(LCD), ST7565R)
CPPDEFS += -DLCD_ST7565R
endif
EXTRABOARDSRC = targets/common_avr/adc_driver.cpp targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp
EXTRABOARDSRC = targets/common_avr/adc_driver.cpp targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp
ifeq ($(SDCARD), YES)
EXTRABOARDSRC += $(FATFSDIR)/ff.c $(FATFSDIR)/fattime.c $(FATFSDIR)/option/ccsbcs.c targets/gruvin9x/diskio.cpp
@@ -1072,6 +1070,14 @@ ifeq ($(TURNIGY_TRANSMITTER_FIX), YES)
endif
endif
ifeq ($(LCD), ST7565R)
CPPDEFS += -DLCD_ST7565R
else ifeq ($(LCD), ERC12864FSF)
CPPDEFS += -DLCD_ERC12864FSF
else ifeq ($(LCD), ST7920)
CPPDEFS += -DLCD_ST7920
endif
ifeq ($(AUTOSWITCH), YES)
CPPDEFS += -DAUTOSWITCH
endif
+100 -45
View File
@@ -47,7 +47,7 @@ void lcdSendCtl(uint8_t val)
{
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
#ifdef LCD_MULTIPLEX
DDRA = 0xFF; // set LCD_DAT pins to output
DDRA = 0xFF; //Set LCD_DAT pins to output
#endif
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
@@ -56,7 +56,7 @@ void lcdSendCtl(uint8_t val)
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
#ifdef LCD_MULTIPLEX
DDRA = 0x00; // set LCD_DAT pins to input
DDRA = 0x00; //Set LCD_DAT pins to input
#endif
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
}
@@ -72,7 +72,7 @@ volatile uint8_t LcdLock ;
const static pm_uchar lcdInitSequence[] PROGMEM =
{
#ifdef LCD_ST7565R
#if defined(LCD_ST7565R)
0xE2, //Initialize the internal functions
0xAE, //DON = 0: display OFF
0xA0, //ADC = 0: normal direction(SEG132->SEG1)
@@ -86,7 +86,7 @@ const static pm_uchar lcdInitSequence[] PROGMEM =
0x22, //24 SV5 SV4 SV3 SV2 SV1 SV0 = 0x18
0xAF, //DON = 1: display ON
0x60 //sets the display start line to zero
#elif LCD_ERC12864FSF
#elif defined(LCD_ERC12864FSF)
0xE2, //Initialize the internal functions
0xAE, //DON = 0: display OFF
0xA1, //ADC = 1: reverse direction(SEG132->SEG1)
@@ -99,7 +99,13 @@ const static pm_uchar lcdInitSequence[] PROGMEM =
0x81, //Set reference voltage Mode
0x2D, //24 SV5 SV4 SV3 SV2 SV1 SV0
0xAF //DON = 1: display ON
#else
#elif defined(LCD_ST7920)
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
#else //ST7565P (default 9x LCD)
0xE2, //Initialize the internal functions
0xAE, //DON = 0: display OFF
0xA1, //ADC = 1: reverse direction(SEG132->SEG1)
@@ -121,58 +127,107 @@ inline void lcdInit()
// ~/txt/flieger/ST7565RV17.pdf from http://www.glyn.de/content.asp?wdid=132&sid=
LCD_LOCK();
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); //LCD_RES
delay_2us();
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); // f524 sbi 0x15, 2 IOADR-PORTC_LCD_CTRL; 21 1
delay_1_5us(1500);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); //LCD reset
#ifdef LCD_ST7920
_delay_ms(1);
#else
delay_2us(); //TODO : verify if can be set to 1ms => so some value for both screen and no #ifdef
#endif
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //LCD normal operation
#ifdef LCD_ST7920
_delay_ms(40);
#else
delay_1_5us(1500); //TODO : verify if can be set to 40 ms instead of 1.5 ms
#endif
for (uint8_t i=0; i<DIM(lcdInitSequence); i++) {
lcdSendCtl(pgm_read_byte(&lcdInitSequence[i])) ;
#ifdef LCD_ST7920
_delay_us(80);
#endif
}
#ifdef LCD_ERC12864FSF
g_eeGeneral.contrast = 0x2D;
#else
g_eeGeneral.contrast = 0x22;
#endif
#ifdef LCD_ERC12864FSF
g_eeGeneral.contrast = 0x2D;
#else
g_eeGeneral.contrast = 0x22;
#endif
LCD_UNLOCK();
}
void lcdSetRefVolt(uint8_t val)
{
LCD_LOCK();
lcdSendCtl(0x81);
lcdSendCtl(val);
LCD_UNLOCK();
#ifndef LCD_ST7920 //No contrast setting in the ST7920 controller
LCD_LOCK();
lcdSendCtl(0x81);
lcdSendCtl(val);
LCD_UNLOCK();
#endif
}
void lcdRefresh()
{
LCD_LOCK();
uint8_t *p=displayBuf;
for(uint8_t y=0; y < 8; y++) {
#ifdef LCD_ST7565R
lcdSendCtl(0x01);
#else
lcdSendCtl(0x04);
#endif
lcdSendCtl(0x10); //column addr 0
lcdSendCtl( y | 0xB0); //page addr y
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
#ifdef LCD_MULTIPLEX
DDRA = 0xFF; // set LCD_DAT pins to output
#endif
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
for (coord_t x=LCD_W; x>0; --x) {
PORTA_LCD_DAT = *p++;
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);
#ifdef LCD_ST7920
uint8_t x_addr = 0;
uint8_t y_addr = 0;
uint16_t line_offset = 0;
uint8_t col_offset = 0;
uint16_t byte_offset = 0;
uint8_t bit_count = 0;
for(uint8_t y=0; y < 64; 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)
byte_offset = line_offset + ( x * 8 ); //Calculate the position of the first byte im array
//adressing the bytes sequential and shift the bits at the correct position, afterwards a OR operation to get all bits in one byte
//the position of the LSB is the left-most position of the byte to the ST7920
PORTA_LCD_DAT = (((displayBuf[byte_offset] & col_offset) >> bit_count) << 7) | (((displayBuf[byte_offset + 1] & col_offset) >> bit_count) << 6) | (((displayBuf[byte_offset + 2] & col_offset) >> bit_count ) << 5) | (((displayBuf[byte_offset + 3] & col_offset) >> bit_count ) << 4) | (((displayBuf[byte_offset + 4] & col_offset) >> bit_count ) << 3) | (((displayBuf[byte_offset + 5] & col_offset) >> bit_count ) << 2) | (((displayBuf[byte_offset + 6] & col_offset) >> bit_count ) << 1) | (((displayBuf[byte_offset + 7] & col_offset) >> bit_count ) << 0);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
_delay_us(8);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
_delay_us(49);
}
}
#else //All other LCD
uint8_t *p=displayBuf;
for(uint8_t y=0; y < 8; y++) {
#ifdef LCD_ST7565R
lcdSendCtl(0x01);
#else
lcdSendCtl(0x04);
#endif
lcdSendCtl(0x10); //Column addr 0
lcdSendCtl( y | 0xB0); //Page addr y
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
#ifdef LCD_MULTIPLEX
DDRA = 0xFF; //Set LCD_DAT pins to output
#endif
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
for (coord_t x=LCD_W; x>0; --x) {
PORTA_LCD_DAT = *p++;
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);
}
#endif
LCD_UNLOCK();
}
}