From d4ed0589e592ee13fe0aff64faf005c3773b74ce Mon Sep 17 00:00:00 2001 From: phdlee Date: Thu, 5 Apr 2018 22:57:07 +0900 Subject: [PATCH] Applied 1602 Tiny LCD Library for reduce program Memory --- ubitx_20/ubitx_lcd_1602i.ino | 81 +++++------ ubitx_20/ubitx_lcd_1602p.ino | 263 +++++++++++++++++++++++++++-------- ubitx_20/ubitx_ui.ino | 7 + 3 files changed, 247 insertions(+), 104 deletions(-) diff --git a/ubitx_20/ubitx_lcd_1602i.ino b/ubitx_20/ubitx_lcd_1602i.ino index 7b56eaf..c8546f0 100644 --- a/ubitx_20/ubitx_lcd_1602i.ino +++ b/ubitx_20/ubitx_lcd_1602i.ino @@ -25,48 +25,23 @@ #ifdef UBITX_DISPLAY_LCD1602I - -/** - * The Raduino board is the size of a standard 16x2 LCD panel. It has three connectors: - * - * First, is an 8 pin connector that provides +5v, GND and six analog input pins that can also be - * configured to be used as digital input or output pins. These are referred to as A0,A1,A2, - * A3,A6 and A7 pins. The A4 and A5 pins are missing from this connector as they are used to - * talk to the Si5351 over I2C protocol. - * - * Second is a 16 pin LCD connector. This connector is meant specifically for the standard 16x2 - * LCD display in 4 bit mode. The 4 bit mode requires 4 data lines and two control lines to work: - * Lines used are : RESET, ENABLE, D4, D5, D6, D7 - * We include the library and declare the configuration of the LCD panel too - */ - +//======================================================================== +//Begin of LCD Hardware define +//======================================================================== #include LiquidCrystal lcd(8,9,10,11,12,13); + +//======================================================================== +//End of LCD Hardware define +//======================================================================== + +//======================================================================== +//Begin of Display Base Routines (Init, printLine..) +//======================================================================== char c[30], b[30]; char printBuff[2][17]; //mirrors what is showing on the two lines of the display -void LCD_Init(void) -{ - lcd.begin(16, 2); - initMeter(); //for Meter Display -} - -void Display_AutoKeyTextIndex(char textIndex) -{ - byte diplayAutoCWLine = 0; - - if ((displayOption1 & 0x01) == 0x01) - diplayAutoCWLine = 1; - lcd.setCursor(0, diplayAutoCWLine); - lcd.write(byteToChar(selectedCWTextIndex)); - lcd.write(':'); -} - - -//======================================================================== -//Display Routine -//======================================================================== const PROGMEM uint8_t meters_bitmap[] = { B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 , //custom 1 B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 , //custom 2 @@ -125,6 +100,12 @@ void initMeter(){ lcd.createChar(6, tmpbytes); } +void LCD_Init(void) +{ + lcd.begin(16, 2); + initMeter(); //for Meter Display +} + //by KD8CEC //0 ~ 25 : 30 over : + 10 void drawMeter(int needle) { @@ -161,7 +142,7 @@ void printLine(unsigned char linenmbr, const char *c) { strcpy(printBuff[linenmbr], c); for (byte i = strlen(c); i < 16; i++) { // add white spaces until the end of the 16 characters line is reached - lcd.print(' '); + lcd.write(' '); } } } @@ -230,14 +211,13 @@ void printLine2ClearAndUpdate(){ line2DisplayStatus = 0; updateDisplay(); } +//=================================================================================== +//End of Display Base Routines +//=================================================================================== -//012...89ABC...Z -char byteToChar(byte srcByte){ - if (srcByte < 10) - return 0x30 + srcByte; - else - return 'A' + srcByte - 10; -} +//=================================================================================== +//Begin of User Interface Routines +//=================================================================================== // this builds up the top line of the display with frequency and mode void updateDisplay() { @@ -335,7 +315,7 @@ void updateDisplay() { else { lcd.setCursor(5,diplayVFOLine); - lcd.write(":"); + lcd.write(':'); } } @@ -557,5 +537,16 @@ void idle_process() } } +void Display_AutoKeyTextIndex(char textIndex) +{ + byte diplayAutoCWLine = 0; + + if ((displayOption1 & 0x01) == 0x01) + diplayAutoCWLine = 1; + lcd.setCursor(0, diplayAutoCWLine); + lcd.write(byteToChar(selectedCWTextIndex)); + lcd.write(':'); +} + #endif diff --git a/ubitx_20/ubitx_lcd_1602p.ino b/ubitx_20/ubitx_lcd_1602p.ino index b37bb45..607d070 100644 --- a/ubitx_20/ubitx_lcd_1602p.ino +++ b/ubitx_20/ubitx_lcd_1602p.ino @@ -23,38 +23,166 @@ #ifdef UBITX_DISPLAY_LCD1602P -//========================================================================= -//Hardware Control routines -//========================================================================= +//======================================================================== +//Begin of TinyLCD Library by KD8CEC +//======================================================================== +/************************************************************************* + LCD1602_TINY Library for 16 x 2 LCD + Referecnce Source : LiquidCrystal.cpp + KD8CEC + This source code is modified version for small program memory + from Arduino LiquidCrystal Library + I wrote this code myself, so there is no license restriction. + So this code allows anyone to write with confidence. + But keep it as long as the original author of the code. + DE Ian KD8CEC +**************************************************************************/ +#define LCD_Command(x) (LCD_Send(x, LOW)) +#define LCD_Write(x) (LCD_Send(x, HIGH)) + +//Define connected PIN +#define LCD_PIN_RS 8 +#define LCD_PIN_EN 9 +uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13}; + +// commands +#define LCD_CLEARDISPLAY 0x01 +#define LCD_RETURNHOME 0x02 +#define LCD_ENTRYMODESET 0x04 +#define LCD_DISPLAYCONTROL 0x08 +#define LCD_CURSORSHIFT 0x10 +#define LCD_FUNCTIONSET 0x20 +#define LCD_SETCGRAMADDR 0x40 +#define LCD_SETDDRAMADDR 0x80 + +// flags for display entry mode +#define LCD_ENTRYRIGHT 0x00 +#define LCD_ENTRYLEFT 0x02 +#define LCD_ENTRYSHIFTINCREMENT 0x01 +#define LCD_ENTRYSHIFTDECREMENT 0x00 + +// flags for display on/off control +#define LCD_DISPLAYON 0x04 +#define LCD_DISPLAYOFF 0x00 +#define LCD_CURSORON 0x02 +#define LCD_CURSOROFF 0x00 +#define LCD_BLINKON 0x01 +#define LCD_BLINKOFF 0x00 + +// flags for display/cursor shift +#define LCD_DISPLAYMOVE 0x08 +#define LCD_CURSORMOVE 0x00 +#define LCD_MOVERIGHT 0x04 +#define LCD_MOVELEFT 0x00 + +// flags for function set +#define LCD_8BITMODE 0x10 +#define LCD_4BITMODE 0x00 +#define LCD_2LINE 0x08 +#define LCD_1LINE 0x00 +#define LCD_5x10DOTS 0x04 +#define LCD_5x8DOTS 0x00 + +void write4bits(uint8_t value) +{ + for (int i = 0; i < 4; i++) + digitalWrite(LCD_PIN_DAT[i], (value >> i) & 0x01); + + digitalWrite(LCD_PIN_EN, LOW); + delayMicroseconds(1); + digitalWrite(LCD_PIN_EN, HIGH); + delayMicroseconds(1); // enable pulse must be >450ns + digitalWrite(LCD_PIN_EN, LOW); + delayMicroseconds(100); // commands need > 37us to settle +} + +void LCD_Send(uint8_t value, uint8_t mode) +{ + digitalWrite(LCD_PIN_RS, mode); + write4bits(value>>4); + write4bits(value); +} + +void LCD1602_Init() +{ + pinMode(LCD_PIN_RS, OUTPUT); + pinMode(LCD_PIN_EN, OUTPUT); + for (int i = 0; i < 4; i++) + pinMode(LCD_PIN_DAT[i], OUTPUT); + + delayMicroseconds(50); + + // Now we pull both RS and R/W low to begin commands + digitalWrite(LCD_PIN_RS, LOW); + digitalWrite(LCD_PIN_EN, LOW); + + // we start in 8bit mode, try to set 4 bit mode + write4bits(0x03); + delayMicroseconds(4500); // wait min 4.1ms + + // second try + write4bits(0x03); + delayMicroseconds(4500); // wait min 4.1ms + + // third go! + write4bits(0x03); + delayMicroseconds(150); + + // finally, set to 4-bit interface + write4bits(0x02); + + // finally, set # lines, font size, etc. + LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE); + + // turn the display on with no cursor or blinking default + LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF); + + // clear it off + LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero + delayMicroseconds(2000); // this command takes a long time! + + LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT); +} + +void LCD_Print(const char *c) +{ + for (int i = 0; i < strlen(c); i++) + { + if (*(c + i) == 0x00) return; + LCD_Write(*(c + i)); + } +} + +void LCD_SetCursor(uint8_t col, uint8_t row) +{ + LCD_Command(LCD_SETDDRAMADDR | (col + row * 0x40)); //0 : 0x00, 1 : 0x40, only for 16 x 2 lcd +} + +void LCD_CreateChar(uint8_t location, uint8_t charmap[]) +{ + location &= 0x7; // we only have 8 locations 0-7 + LCD_Command(LCD_SETCGRAMADDR | (location << 3)); + for (int i=0; i<8; i++) + LCD_Write(charmap[i]); +} +//======================================================================== +//End of TinyLCD Library by KD8CEC +//======================================================================== + +/* #include LiquidCrystal lcd(8,9,10,11,12,13); +*/ + +//======================================================================== +//Begin of Display Base Routines (Init, printLine..) +//======================================================================== char c[30], b[30]; char printBuff[2][17]; //mirrors what is showing on the two lines of the display -void LCD_Init(void) -{ - lcd.begin(16, 2); - initMeter(); //for Meter Display -} - -void Display_AutoKeyTextIndex(char textIndex) -{ - byte diplayAutoCWLine = 0; - - if ((displayOption1 & 0x01) == 0x01) - diplayAutoCWLine = 1; - lcd.setCursor(0, diplayAutoCWLine); - lcd.write(byteToChar(selectedCWTextIndex)); - lcd.write(':'); -} - - -//======================================================================== -//Display Routine -//======================================================================== const PROGMEM uint8_t meters_bitmap[] = { B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 , //custom 1 B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 , //custom 2 @@ -86,31 +214,37 @@ void initMeter(){ for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(plock_bitmap + i); - lcd.createChar(0, tmpbytes); + LCD_CreateChar(0, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i); - lcd.createChar(1, tmpbytes); + LCD_CreateChar(1, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8); - lcd.createChar(2, tmpbytes); + LCD_CreateChar(2, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16); - lcd.createChar(3, tmpbytes); + LCD_CreateChar(3, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24); - lcd.createChar(4, tmpbytes); + LCD_CreateChar(4, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32); - lcd.createChar(5, tmpbytes); + LCD_CreateChar(5, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40); - lcd.createChar(6, tmpbytes); + LCD_CreateChar(6, tmpbytes); +} + +void LCD_Init(void) +{ + LCD1602_Init(); + initMeter(); //for Meter Display } //by KD8CEC @@ -136,20 +270,17 @@ void drawMeter(int needle) { lcdMeter[5] = 0x20; } - - // The generic routine to display one line on the LCD void printLine(unsigned char linenmbr, const char *c) { if ((displayOption1 & 0x01) == 0x01) linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle - if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change - lcd.setCursor(0, linenmbr); // place the cursor at the beginning of the selected line - lcd.print(c); + LCD_SetCursor(0, linenmbr); // place the cursor at the beginning of the selected line + LCD_Print(c); strcpy(printBuff[linenmbr], c); for (byte i = strlen(c); i < 16; i++) { // add white spaces until the end of the 16 characters line is reached - lcd.print(' '); + LCD_Write(' '); } } } @@ -175,26 +306,28 @@ void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, b if ((displayOption1 & 0x01) == 0x01) linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle - lcd.setCursor(lcdColumn, linenmbr); + LCD_SetCursor(lcdColumn, linenmbr); for (byte i = eepromStartIndex; i <= eepromEndIndex; i++) { if (++lcdColumn <= LCD_MAX_COLUMN) - lcd.write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i)); + LCD_Write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i)); else break; } for (byte i = lcdColumn; i < 16; i++) //Right Padding by Space - lcd.write(' '); + LCD_Write(' '); } // short cut to print to the first line -void printLine1(const char *c){ +void printLine1(const char *c) +{ printLine(1,c); } // short cut to print to the first line -void printLine2(const char *c){ +void printLine2(const char *c) +{ printLine(0,c); } @@ -219,14 +352,16 @@ void printLine2ClearAndUpdate(){ updateDisplay(); } -//012...89ABC...Z -char byteToChar(byte srcByte){ - if (srcByte < 10) - return 0x30 + srcByte; - else - return 'A' + srcByte - 10; -} +//================================================================================== +//End of Display Base Routines +//================================================================================== + +//================================================================================== +//Begin of User Interface Routines +//================================================================================== + +//Main Display // this builds up the top line of the display with frequency and mode void updateDisplay() { // tks Jack Purdum W8TEE @@ -313,17 +448,17 @@ void updateDisplay() { if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) || (vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) { - lcd.setCursor(5,diplayVFOLine); - lcd.write((uint8_t)0); + LCD_SetCursor(5,diplayVFOLine); + LCD_Write((uint8_t)0); } else if (isCWAutoMode == 2){ - lcd.setCursor(5,diplayVFOLine); - lcd.write(0x7E); + LCD_SetCursor(5,diplayVFOLine); + LCD_Write(0x7E); } else { - lcd.setCursor(5,diplayVFOLine); - lcd.write(":"); + LCD_SetCursor(5,diplayVFOLine); + LCD_Write(':'); } } @@ -360,9 +495,7 @@ void updateLine2Buffer(char displayType) return; } //end of ritOn display - //====================================================== //other VFO display - //====================================================== if (vfoActive == VFO_B) { tmpFreq = vfoA; @@ -508,10 +641,10 @@ void DisplayMeter(byte meterType, byte meterValue, char drawPosition) if ((displayOption1 & 0x01) == 0x01) lineNumber = 1; - lcd.setCursor(drawPosition, lineNumber); + LCD_SetCursor(drawPosition, lineNumber); for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6 - lcd.write(lcdMeter[i]); + LCD_Write(lcdMeter[i]); } } @@ -545,5 +678,17 @@ void idle_process() } } +//AutoKey LCD Display Routine +void Display_AutoKeyTextIndex(char textIndex) +{ + byte diplayAutoCWLine = 0; + + if ((displayOption1 & 0x01) == 0x01) + diplayAutoCWLine = 1; + LCD_SetCursor(0, diplayAutoCWLine); + LCD_Write(byteToChar(selectedCWTextIndex)); + LCD_Write(':'); +} + #endif diff --git a/ubitx_20/ubitx_ui.ino b/ubitx_20/ubitx_ui.ino index 27d570f..4907282 100644 --- a/ubitx_20/ubitx_ui.ino +++ b/ubitx_20/ubitx_ui.ino @@ -6,6 +6,13 @@ * quickly cleared up. */ + char byteToChar(byte srcByte){ + if (srcByte < 10) + return 0x30 + srcByte; + else + return 'A' + srcByte - 10; +} + //returns true if the button is pressed int btnDown(void){ if (digitalRead(FBUTTON) == HIGH)