ST7920 support added for 9x and M2560 boards
Merge of olterion ST7920 driver, thanks :) Draft... please check !
This commit is contained in:
+13
-7
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user