diff --git a/ubitx_20/ubitx.h b/ubitx_20/ubitx.h index 41d3555..51bdf19 100644 --- a/ubitx_20/ubitx.h +++ b/ubitx_20/ubitx.h @@ -24,10 +24,10 @@ //Depending on the type of LCD mounted on the uBITX, uncomment one of the options below. //You must select only one. -//#define UBITX_DISPLAY_LCD1602P //LCD mounted on unmodified uBITX +#define UBITX_DISPLAY_LCD1602P //LCD mounted on unmodified uBITX //#define UBITX_DISPLAY_LCD1602I //I2C type 16 x 02 LCD //#define UBITX_DISPLAY_LCD1602I_CUST //I2C type 16 x 02 Custom Tiny Library -#define UBITX_DISPLAY_LCD2004P //24 x 04 LCD +//#define UBITX_DISPLAY_LCD2004P //24 x 04 LCD //#define UBITX_DISPLAY_LCD2004I //I2C type 24 x 04 LCD //============================================================================== @@ -95,6 +95,7 @@ extern unsigned long frequency; extern byte WsprMSGCount; +extern byte sMeterLevels[9]; extern void printLine1(const char *c); extern void printLine2(const char *c); diff --git a/ubitx_20/ubitx_20.ino b/ubitx_20/ubitx_20.ino index 5b7b13a..b80245e 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -1,11 +1,19 @@ //Firmware Version -#define FIRMWARE_VERSION_INFO F("CEC v1.071") +//+ : This symbol identifies the firmware. +// It was originally called 'CEC V1.072' but it is too long to waste the LCD window. +// I do not want to make this Firmware users's uBITX messy with my callsign. +// Putting one alphabet in front of 'v' has a different meaning. +// So I put + in the sense that it was improved one by one based on Original Firmware. +// This firmware has been gradually changed based on the original firmware created by Farhan, Jack, Jerry and others. + +#define FIRMWARE_VERSION_INFO F("+v1.072") #define FIRMWARE_VERSION_NUM 0x02 //1st Complete Project : 1 (Version 1.061), 2st Project : 2 /** Cat Suppoort uBITX CEC Version + This firmware has been gradually changed based on the original firmware created by Farhan, Jack, Jerry and others. Most features(TX, Frequency Range, Ham Band, TX Control, CW delay, start Delay... more) have been added by KD8CEC. - However, the license rules are subject to the original source rules. + My wish is to keep the original author's Comment as long as the meaning does not change much, even if the code looks a bit long. Ian KD8CEC Original source comment ------------------------------------------------------------- @@ -172,6 +180,7 @@ unsigned long SDR_Center_Freq; // unsigned long beforeIdle_ProcessTime = 0; //for check Idle time byte line2DisplayStatus = 0; //0:Clear, 1 : menu, 1: DisplayFrom Idle, char lcdMeter[17]; +byte sMeterLevels[9]; byte isIFShift = 0; //1 = ifShift, 2 extend int ifShiftValue = 0; // @@ -183,8 +192,8 @@ int ifShiftValue = 0; // //Ham Band #define MAX_LIMIT_RANGE 10 //because limited eeprom size -byte useHamBandCount = 0; //0 use full range frequency -byte tuneTXType = 0; //0 : use full range, 1 : just Change Dial speed, 2 : just ham band change, but can general band by tune, 3 : only ham band (just support 0, 2 (0.26 version)) +byte useHamBandCount = 0; //0 use full range frequency +byte tuneTXType = 0; //0 : use full range, 1 : just Change Dial speed, 2 : just ham band change, but can general band by tune, 3 : only ham band (just support 0, 2 (0.26 version)) //100 : use full range but not TX on general band, 101 : just change dial speed but.. 2 : jut... but.. 3 : only ham band (just support 100, 102 (0.26 version)) unsigned int hamBandRange[MAX_LIMIT_RANGE][2]; // = //Khz because reduce use memory @@ -819,6 +828,10 @@ void initSettings(){ EEPROM.get(DISPLAY_OPTION1, displayOption1); EEPROM.get(DISPLAY_OPTION2, displayOption2); + for (byte i = 0; i < 8; i++) { + sMeterLevels[i + 1] = EEPROM.read(S_METER_LEVELS + i); + } + //User callsign information if (EEPROM.read(USER_CALLSIGN_KEY) == 0x59) userCallsignLength = EEPROM.read(USER_CALLSIGN_LEN); //MAXIMUM 18 LENGTH diff --git a/ubitx_20/ubitx_eemap.h b/ubitx_20/ubitx_eemap.h index dc10487..56855c8 100644 --- a/ubitx_20/ubitx_eemap.h +++ b/ubitx_20/ubitx_eemap.h @@ -50,6 +50,9 @@ // 256 ~ 1023 (EEProm Section #1) // 255 ~ 101 (EEProm Section #2) //============================================================================== +#define S_METER_LEVELS 230 //LEVEL0 ~ LEVEL7 + + #define ADVANCED_FREQ_OPTION1 240 //Bit0: use IFTune_Value, Bit1 : use Stored enabled SDR Mode, Bit2 : dynamic sdr frequency #define IF1_CAL 241 #define ENABLE_SDR 242 diff --git a/ubitx_20/ubitx_lcd_1602i.ino b/ubitx_20/ubitx_lcd_1602i.ino index 21def44..2fbfd87 100644 --- a/ubitx_20/ubitx_lcd_1602i.ino +++ b/ubitx_20/ubitx_lcd_1602i.ino @@ -409,13 +409,13 @@ void updateLine2Buffer(char displayType) //EXAMPLE #1 if ((displayOption1 & 0x04) == 0x00) //none scroll display - line2Buffer[6] = 'k'; + line2Buffer[6] = 'M'; else { //example #2 if (freqScrollPosition++ > 18) //none scroll display time { - line2Buffer[6] = 'k'; + line2Buffer[6] = 'M'; if (freqScrollPosition > 25) freqScrollPosition = -1; } diff --git a/ubitx_20/ubitx_lcd_1602iian.ino b/ubitx_20/ubitx_lcd_1602iian.ino index 9d11bb4..0512339 100644 --- a/ubitx_20/ubitx_lcd_1602iian.ino +++ b/ubitx_20/ubitx_lcd_1602iian.ino @@ -570,13 +570,13 @@ void updateLine2Buffer(char displayType) //EXAMPLE #1 if ((displayOption1 & 0x04) == 0x00) //none scroll display - line2Buffer[6] = 'k'; + line2Buffer[6] = 'M'; else { //example #2 if (freqScrollPosition++ > 18) //none scroll display time { - line2Buffer[6] = 'k'; + line2Buffer[6] = 'M'; if (freqScrollPosition > 25) freqScrollPosition = -1; } diff --git a/ubitx_20/ubitx_lcd_1602p.ino b/ubitx_20/ubitx_lcd_1602p.ino index b20cba5..8b2f82b 100644 --- a/ubitx_20/ubitx_lcd_1602p.ino +++ b/ubitx_20/ubitx_lcd_1602p.ino @@ -175,7 +175,8 @@ void LCD_CreateChar(uint8_t location, uint8_t charmap[]) #include LiquidCrystal lcd(8,9,10,11,12,13); */ - +//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA +#define OPTION_SKINNYBARS //======================================================================== //Begin of Display Base Routines (Init, printLine..) @@ -183,93 +184,12 @@ LiquidCrystal lcd(8,9,10,11,12,13); char c[30], b[30]; char printBuff[2][17]; //mirrors what is showing on the two lines of the display -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 - B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100 , //custom 3 - B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110 , //custom 4 - B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 , //custom 5 - B01000, B11100, B01000, B00000, B10111, B10101, B10101, B10111 //custom 6 -}; - -PGM_P p_metes_bitmap = reinterpret_cast(meters_bitmap); - -const PROGMEM uint8_t lock_bitmap[8] = { - 0b01110, - 0b10001, - 0b10001, - 0b11111, - 0b11011, - 0b11011, - 0b11111, - 0b00000}; -PGM_P plock_bitmap = reinterpret_cast(lock_bitmap); - - -// initializes the custom characters -// we start from char 1 as char 0 terminates the string! -void initMeter(){ - uint8_t tmpbytes[8]; - byte i; - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(plock_bitmap + i); - LCD_CreateChar(0, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i); - LCD_CreateChar(1, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8); - LCD_CreateChar(2, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16); - LCD_CreateChar(3, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24); - LCD_CreateChar(4, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32); - LCD_CreateChar(5, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40); - LCD_CreateChar(6, tmpbytes); -} - void LCD_Init(void) { LCD1602_Init(); initMeter(); //for Meter Display } -//by KD8CEC -//0 ~ 25 : 30 over : + 10 -void drawMeter(int needle) { - //5Char + O over - int i; - - for (i = 0; i < 5; i++) { - if (needle >= 5) - lcdMeter[i] = 5; //full - else if (needle > 0) - lcdMeter[i] = needle; //full - else //0 - lcdMeter[i] = 0x20; - - needle -= 5; - } - - if (needle > 0) - lcdMeter[5] = 6; - else - 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) @@ -534,13 +454,13 @@ void updateLine2Buffer(char displayType) //EXAMPLE #1 if ((displayOption1 & 0x04) == 0x00) //none scroll display - line2Buffer[6] = 'k'; + line2Buffer[6] = 'M'; else { //example #2 if (freqScrollPosition++ > 18) //none scroll display time { - line2Buffer[6] = 'k'; + line2Buffer[6] = 'M'; if (freqScrollPosition > 25) freqScrollPosition = -1; } @@ -625,7 +545,13 @@ void updateLine2Buffer(char displayType) line2Buffer[13] = ' '; //Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb - if (cwKeyType == 0) + if (sdrModeOn == 1) + { + line2Buffer[13] = 'S'; + line2Buffer[14] = 'D'; + line2Buffer[15] = 'R'; + } + else if (cwKeyType == 0) { line2Buffer[14] = 'S'; line2Buffer[15] = 'T'; @@ -648,20 +574,26 @@ void DisplayMeter(byte meterType, byte meterValue, char drawPosition) { if (meterType == 0 || meterType == 1 || meterType == 2) { - drawMeter(meterValue); //call original source code + drawMeter(meterValue); int lineNumber = 0; if ((displayOption1 & 0x01) == 0x01) lineNumber = 1; LCD_SetCursor(drawPosition, lineNumber); - for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6 - LCD_Write(lcdMeter[i]); + //for (int i = 0; i <26; i++) //meter 5 + +db 1 = 6 + LCD_Write(lcdMeter[0]); + LCD_Write(lcdMeter[1]); } } byte testValue = 0; char checkCount = 0; + +int currentSMeter = 0; +//byte sMeterLevels[] = {0, 1, 4, 10, 18, 35, 63, 91, 117}; //John's default Value (divide / 4) +byte scaledSMeter = 0; + void idle_process() { //space for user graphic display @@ -679,6 +611,7 @@ void idle_process() line2DisplayStatus = 2; checkCount = 0; } + } //EX for Meters /* @@ -686,7 +619,29 @@ void idle_process() if (testValue > 30) testValue = 0; */ - } + + //S-Meter Display + if ((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) + { + int newSMeter; + + //VK2ETA S-Meter from MAX9814 TC pin / divide 4 by KD8CEC for reduce EEPromSize + newSMeter = analogRead(ANALOG_SMETER); + + //Faster attack, Slower release + currentSMeter = (newSMeter > currentSMeter ? ((currentSMeter * 3 + newSMeter * 7) + 5) / 10 : ((currentSMeter * 7 + newSMeter * 3) + 5) / 10) / 4; + + scaledSMeter = 0; + for (byte s = 8; s >= 1; s--) { + if (currentSMeter > sMeterLevels[s]) { + scaledSMeter = s; + break; + } + } + + DisplayMeter(0, scaledSMeter, 14); + } //end of S-Meter + } } diff --git a/ubitx_20/ubitx_lcd_2004p.ino b/ubitx_20/ubitx_lcd_2004p.ino index 7cec500..fb29ec0 100644 --- a/ubitx_20/ubitx_lcd_2004p.ino +++ b/ubitx_20/ubitx_lcd_2004p.ino @@ -22,7 +22,6 @@ **************************************************************************/ #ifdef UBITX_DISPLAY_LCD2004P - //======================================================================== //Begin of TinyLCD Library by KD8CEC //======================================================================== @@ -176,7 +175,8 @@ void LCD_CreateChar(uint8_t location, uint8_t charmap[]) #include LiquidCrystal lcd(8,9,10,11,12,13); */ - +//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA +//#define OPTION_SKINNYBARS //======================================================================== //Begin of Display Base Routines (Init, printLine..) @@ -184,92 +184,12 @@ LiquidCrystal lcd(8,9,10,11,12,13); char c[30], b[30]; char printBuff[4][20]; //mirrors what is showing on the two lines of the display -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 - B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100 , //custom 3 - B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110 , //custom 4 - B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 , //custom 5 - B01000, B11100, B01000, B00000, B10111, B10101, B10101, B10111 //custom 6 -}; - -PGM_P p_metes_bitmap = reinterpret_cast(meters_bitmap); - -const PROGMEM uint8_t lock_bitmap[8] = { - 0b01110, - 0b10001, - 0b10001, - 0b11111, - 0b11011, - 0b11011, - 0b11111, - 0b00000}; -PGM_P plock_bitmap = reinterpret_cast(lock_bitmap); - - -// initializes the custom characters -// we start from char 1 as char 0 terminates the string! -void initMeter(){ - uint8_t tmpbytes[8]; - byte i; - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(plock_bitmap + i); - LCD_CreateChar(0, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i); - LCD_CreateChar(1, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8); - LCD_CreateChar(2, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16); - LCD_CreateChar(3, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24); - LCD_CreateChar(4, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32); - LCD_CreateChar(5, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40); - LCD_CreateChar(6, tmpbytes); -} - void LCD_Init(void) { LCD2004_Init(); initMeter(); //for Meter Display } -//by KD8CEC -//0 ~ 25 : 30 over : + 10 -void drawMeter(int needle) { - //5Char + O over - int i; - - for (i = 0; i < 5; i++) { - if (needle >= 5) - lcdMeter[i] = 5; //full - else if (needle > 0) - lcdMeter[i] = needle; //full - else //0 - lcdMeter[i] = 0x20; - - needle -= 5; - } - - if (needle > 0) - lcdMeter[5] = 6; - else - lcdMeter[5] = 0x20; -} // The generic routine to display one line on the LCD void printLine(unsigned char linenmbr, const char *c) { @@ -289,10 +209,10 @@ void printLine(unsigned char linenmbr, const char *c) { void printLineF(char linenmbr, const __FlashStringHelper *c) { int i; - char tmpBuff[20]; + char tmpBuff[21]; PGM_P p = reinterpret_cast(c); - for (i = 0; i < 17; i++){ + for (i = 0; i < 21; i++){ unsigned char fChar = pgm_read_byte(p++); tmpBuff[i] = fChar; if (fChar == 0) @@ -324,7 +244,7 @@ void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, b // short cut to print to the first line void printLine1(const char *c) { - printLine(2,c); + printLine(1,c); } // short cut to print to the first line void printLine2(const char *c) @@ -340,7 +260,7 @@ void clearLine2() // short cut to print to the first line void printLine1Clear(){ - printLine(2,""); + printLine(1,""); } // short cut to print to the first line void printLine2Clear(){ @@ -368,6 +288,7 @@ void updateDisplay() { // tks Jack Purdum W8TEE // replaced fsprint commmands by str commands for code size reduction // replace code for Frequency numbering error (alignment, point...) by KD8CEC + // i also Very TNX Purdum for good source code int i; unsigned long tmpFreq = frequency; // @@ -409,6 +330,7 @@ void updateDisplay() { strcpy(c, "CWU "); } } + if (vfoActive == VFO_A) // VFO A is active strcat(c, "A:"); else @@ -437,18 +359,18 @@ void updateDisplay() { c[i] = ' '; } + if (sdrModeOn) + strcat(c, " SDR"); + else + strcat(c, " SPK"); + //remarked by KD8CEC //already RX/TX status display, and over index (20 x 4 LCD) //if (inTx) // strcat(c, " TX"); + printLine(1, c); - c[16] = ' '; - c[17] = 'H'; - c[18] = 'z'; - - printLine(2, c); - - byte diplayVFOLine = 2; + byte diplayVFOLine = 1; if ((displayOption1 & 0x01) == 0x01) diplayVFOLine = 0; @@ -481,9 +403,7 @@ int freqScrollPosition = 0; //warning : unused parameter 'displayType' <-- ignore, this is reserve void updateLine2Buffer(char displayType) { - //Second Frequency Display unsigned long tmpFreq = 0; - if (ritOn) { strcpy(line2Buffer, "RitTX:"); @@ -512,77 +432,61 @@ void updateLine2Buffer(char displayType) line2Buffer[i] = ' '; } - //return; + return; } //end of ritOn display - else + + //other VFO display + if (vfoActive == VFO_B) { - - //other VFO display - if (vfoActive == VFO_B) - { - tmpFreq = vfoA; - } - else - { - tmpFreq = vfoB; - } - - // EXAMPLE 1 & 2 - //U14.150.100 - //display frequency - for (int i = 9; i >= 0; i--) { - if (tmpFreq > 0) { - if (i == 2 || i == 6) line2Buffer[i] = '.'; - else { - line2Buffer[i] = tmpFreq % 10 + 0x30; - tmpFreq /= 10; - } + tmpFreq = vfoA; + } + else + { + tmpFreq = vfoB; + } + + // EXAMPLE 1 & 2 + //U14.150.100 + //display frequency + for (int i = 9; i >= 0; i--) { + if (tmpFreq > 0) { + if (i == 2 || i == 6) line2Buffer[i] = '.'; + else { + line2Buffer[i] = tmpFreq % 10 + 0x30; + tmpFreq /= 10; } - else - line2Buffer[i] = ' '; - } - - - line2Buffer[6] = 'k'; - line2Buffer[7] = ' '; - line2Buffer[8] = 'S'; - //strcat(line2Buffer, "k SDR:"); - - if (sdrModeOn == 0) - { - line2Buffer[9] = 'P'; - line2Buffer[10] = 'K'; } else - { - line2Buffer[9] = 'D'; - line2Buffer[10] = 'R'; - } - - line2Buffer[11] = ' '; - + line2Buffer[i] = ' '; + } + + memset(&line2Buffer[10], ' ', 10); + + if (isIFShift) + { + line2Buffer[6] = 'M'; + line2Buffer[7] = ' '; //IFShift Offset Value - line2Buffer[12] = 'I'; - line2Buffer[13] = 'F'; + line2Buffer[8] = 'I'; + line2Buffer[9] = 'F'; - line2Buffer[14] = ifShiftValue >= 0 ? '+' : 0; - line2Buffer[15] = 0; - line2Buffer[16] = ' '; - - //15, 16, 17, 18, 19 + line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0; + line2Buffer[11] = 0; + line2Buffer[12] = ' '; + + //11, 12, 13, 14, 15 memset(b, 0, sizeof(b)); ltoa(ifShiftValue, b, DEC); strncat(line2Buffer, b, 5); - } //end of else - printLine(1, line2Buffer); - - memset(line2Buffer, ' ', 20); + for (int i = 12; i < 17; i++) + { + if (line2Buffer[i] == 0) + line2Buffer[i] = ' '; + } + } // end of display IF + else // step & Key Type display { - //if (isDirectCall != 0) - // return; - - memset(&line2Buffer[8], ' ', 8); //Step long tmpStep = arTuneStep[tuneStepIndex -1]; @@ -592,7 +496,7 @@ void updateLine2Buffer(char displayType) isStepKhz = 2; } - for (int i = 10; i >= 8 - isStepKhz; i--) { + for (int i = 14; i >= 12 - isStepKhz; i--) { if (tmpStep > 0) { line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30; tmpStep /= 10; @@ -603,29 +507,30 @@ void updateLine2Buffer(char displayType) if (isStepKhz == 0) { - line2Buffer[11] = 'H'; - line2Buffer[12] = 'z'; + line2Buffer[15] = 'H'; + line2Buffer[16] = 'z'; } - - line2Buffer[13] = ' '; - - //Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb - if (cwKeyType == 0) - { - line2Buffer[14] = 'S'; - line2Buffer[15] = 'T'; - } - else if (cwKeyType == 1) - { - line2Buffer[14] = 'I'; - line2Buffer[15] = 'A'; - } - else - { - line2Buffer[14] = 'I'; - line2Buffer[15] = 'B'; - } } + + line2Buffer[17] = ' '; + + //Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb + if (cwKeyType == 0) + { + line2Buffer[18] = 'S'; + line2Buffer[19] = 'T'; + } + else if (cwKeyType == 1) + { + line2Buffer[18] = 'I'; + line2Buffer[19] = 'A'; + } + else + { + line2Buffer[18] = 'I'; + line2Buffer[19] = 'B'; + } + } //meterType : 0 = S.Meter, 1 : P.Meter @@ -633,20 +538,93 @@ void DisplayMeter(byte meterType, byte meterValue, char drawPosition) { if (meterType == 0 || meterType == 1 || meterType == 2) { - drawMeter(meterValue); //call original source code - int lineNumber = 0; - if ((displayOption1 & 0x01) == 0x01) - lineNumber = 1; + drawMeter(meterValue); + //int lineNumber = 0; + //if ((displayOption1 & 0x01) == 0x01) + //lineNumber = 1; - LCD_SetCursor(drawPosition, lineNumber); - + LCD_SetCursor(drawPosition, 2); + LCD_Write('S'); + LCD_Write(':'); for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6 LCD_Write(lcdMeter[i]); } } + +//meterType : 0 = S.Meter, 1 = Forward Power Meter, 2 = SWR Meter +void DisplayMeter(byte meterType, int meterValue, char drawPosition) +{ + +#ifdef OPTION_SKINNYBARS //We want skinny meter bars with more text/numbers + memcpy(&(line2Buffer[drawPosition]), " ", 8); //Blank that section of 8 characters first + if (meterType == 0) { //SWR meter + drawMeter(meterValue); //Only 2 characters + line2Buffer[drawPosition] = 'S'; + byte sValue = round((float)meterValue * 1.5); //6 bars available only to show 9 S values + sValue = sValue > 9 ? 9 : sValue; //Max S9 + line2Buffer[drawPosition + 1] = '0' + sValue; //0 to 9 + memcpy(&(line2Buffer[drawPosition + 2]), lcdMeter, 2); //Copy the S-Meter bars + //Add the +10, +20, etc... + if (meterValue > 6) { + //We are over S9 + line2Buffer[drawPosition + 4] = '+'; + line2Buffer[drawPosition + 5] = '0' + meterValue - 6; //1,2,3 etc... + line2Buffer[drawPosition + 6] = '0'; + } + } else if (meterType == 1) { //Forward Power + drawMeter(round((float)meterValue / 40)); //4 watts per bar + //meterValue contains power value x 10 (one decimal point) + line2Buffer[drawPosition] = 'P'; + meterValue = meterValue > 999 ? 999 : meterValue; //Limit to 99.9 watts!!!! + //Remove decimal value and divide by 10 + meterValue = round((float)meterValue / 10); + if (meterValue < 10) { + line2Buffer[drawPosition + 1] = ' '; + line2Buffer[drawPosition + 2] = '0' + meterValue; //0 to 9 + } else { + line2Buffer[drawPosition + 1] = '0' + meterValue / 10; + line2Buffer[drawPosition + 2] = '0' + (meterValue - ((meterValue / 10) * 10)); + } + line2Buffer[drawPosition + 3] = 'W'; + memcpy(&(line2Buffer[drawPosition + 4]), lcdMeter, 2); //Copy the S-Meter bars + } else { //SWR + drawMeter((int)(((float)meterValue - 21) / 100)); //no bar = < 1.2, then 1 bar = 1.2 to 2.2, 2 bars = 2.2 to 3.2, etc... + //meterValue contains SWR x 100 (two decimal point) + memcpy(&(line2Buffer[drawPosition]), "SWR", 3); + meterValue = round((float)meterValue / 10); //We now have swr x 10 (1 decimal point) + if (meterValue < 100) { //10 to 99, no decimal point + //Draw the decimal value + line2Buffer[drawPosition + 3] = '0' + meterValue / 10; + line2Buffer[drawPosition + 4] = '.'; + line2Buffer[drawPosition + 5] = '0' + (meterValue - ((meterValue / 10) * 10)); + } else { + memcpy(&(line2Buffer[drawPosition + 3]), "10+", 3); //over 10 + } + memcpy(&(line2Buffer[drawPosition + 6]), lcdMeter, 2); //Copy the S-Meter bars + } +#else //We want fat bars, easy to read, with less text/numbers + //Serial.print("In displaymeter, meterValue: "); Serial.println(meterValue); + drawMeter(meterValue); + //Always line 2 + char sym = 'S'; + if (meterType == 1) sym = 'P'; + else if (meterType == 2) sym = 'R'; //For SWR + line2Buffer[drawPosition] = sym; + memcpy(&(line2Buffer[drawPosition + 1]), lcdMeter, 7); +#endif //OPTION_SKINNYBARS + +} + + byte testValue = 0; char checkCount = 0; + +int currentSMeter = 0; +//int sMeterLevels[] = {0, 5, 17, 41, 74, 140, 255, 365, 470}; +byte scaledSMeter = 0; + +//execute interval : 0.25sec void idle_process() { //space for user graphic display @@ -664,14 +642,45 @@ void idle_process() line2DisplayStatus = 2; checkCount = 0; } - - //EX for Meters - /* - DisplayMeter(0, testValue++, 7); - if (testValue > 30) - testValue = 0; - */ } + + //EX for Meters + /* + DisplayMeter(0, testValue++, 0); + if (testValue > 30) + testValue = 0; + */ + + //Sample + //DisplayMeter(0, analogRead(ANALOG_SMETER) / 30, 0); + //DisplayMeter(0, analogRead(ANALOG_SMETER) / 10, 0); + //delay_background(10, 0); + //DisplayMeter(0, analogRead(ANALOG_SMETER), 0); + //if (testValue > 30) + // testValue = 0; + + //S-Meter Display + if ((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) + { + int newSMeter; + + //VK2ETA S-Meter from MAX9814 TC pin + newSMeter = analogRead(ANALOG_SMETER); + + //Faster attack, Slower release + currentSMeter = (newSMeter > currentSMeter ? ((currentSMeter * 3 + newSMeter * 7) + 5) / 10 : ((currentSMeter * 7 + newSMeter * 3) + 5) / 10); + + scaledSMeter = 0; + for (byte s = 8; s >= 1; s--) { + if (currentSMeter > sMeterLevels[s]) { + scaledSMeter = s; + break; + } + } + + DisplayMeter(0, scaledSMeter, 0); + } //end of S-Meter + } } @@ -689,8 +698,7 @@ void Display_AutoKeyTextIndex(byte textIndex) void DisplayCallsign(byte callSignLength) { - printLineFromEEPRom(3, 12, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) - //delay(500); + printLineFromEEPRom(3, 20 - userCallsignLength, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) } void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) @@ -698,5 +706,4 @@ void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) printLineF(3, fwVersionInfo); } - #endif diff --git a/ubitx_20/ubitx_menu.ino b/ubitx_20/ubitx_menu.ino index bddaea6..eac44b0 100644 --- a/ubitx_20/ubitx_menu.ino +++ b/ubitx_20/ubitx_menu.ino @@ -59,12 +59,10 @@ void menuBand(int btn){ btnPressCount = 0; if (tuneTXType > 0) { //Just toggle 0 <-> 2, if tuneTXType is 100, 100 -> 0 -> 2 tuneTXType = 0; - //printLineF2(F("General mode")); printLineF2(F("General")); } else { tuneTXType = 2; - //printLineF2(F("Ham band mode")); printLineF2(F("Ham band")); } delay_background(1000, 0); diff --git a/ubitx_20/ubitx_ui.ino b/ubitx_20/ubitx_ui.ino index 4907282..e2fad8d 100644 --- a/ubitx_20/ubitx_ui.ino +++ b/ubitx_20/ubitx_ui.ino @@ -6,6 +6,153 @@ * quickly cleared up. */ + +/* +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 + B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100 , //custom 3 + B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110 , //custom 4 + B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 , //custom 5 + B01000, B11100, B01000, B00000, B10111, B10101, B10101, B10111 //custom 6 +}; +*/ + +//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA + +#ifdef OPTION_SKINNYBARS //We want skninny bars with more text +//VK2ETA modded "Skinny" bitmaps +const PROGMEM uint8_t meters_bitmap[] = { + // B01110, B10001, B10001, B11111, B11011, B11011, B11111, B00000, //Padlock Symbol, for merging. Not working, see below + B00000, B00000, B00000, B00000, B00000, B00000, B00000, B10000, //shortest bar + B00000, B00000, B00000, B00000, B00000, B00000, B00100, B10100, + B00000, B00000, B00000, B00000, B00000, B00001, B00101, B10101, + B00000, B00000, B00000, B00000, B10000, B10000, B10000, B10000, + B00000, B00000, B00000, B00100, B10100, B10100, B10100, B10100, + B00000, B00000, B00001, B00101, B10101, B10101, B10101, B10101, //tallest bar + B00000, B00010, B00111, B00010, B01000, B11100, B01000, B00000, // ++ sign +}; +#else +//VK2ETA "Fat" bars, easy to read, with less text +const PROGMEM uint8_t meters_bitmap[] = { + // B01110, B10001, B10001, B11111, B11011, B11011, B11111, B00000, //Padlock Symbol, for merging. Not working, see below + B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111, //shortest bar + B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111, + B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111, + B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111, + B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111, + B00000, B00000, B11111, B11111, B11111, B11111, B11111, B11111, //tallest bar + B00000, B00010, B00111, B00010, B01000, B11100, B01000, B00000, // ++ sign +}; +#endif //OPTION_SKINNYBARS +PGM_P p_metes_bitmap = reinterpret_cast(meters_bitmap); + +const PROGMEM uint8_t lock_bitmap[8] = { + 0b01110, + 0b10001, + 0b10001, + 0b11111, + 0b11011, + 0b11011, + 0b11111, + 0b00000}; +PGM_P plock_bitmap = reinterpret_cast(lock_bitmap); + + +// initializes the custom characters +// we start from char 1 as char 0 terminates the string! +void initMeter(){ + uint8_t tmpbytes[8]; + byte i; + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(plock_bitmap + i); + LCD_CreateChar(0, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i); + LCD_CreateChar(1, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8); + LCD_CreateChar(2, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16); + LCD_CreateChar(3, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24); + LCD_CreateChar(4, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32); + LCD_CreateChar(5, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40); + LCD_CreateChar(6, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 48); + LCD_CreateChar(6, tmpbytes); +} + + +//by KD8CEC +//0 ~ 25 : 30 over : + 10 +/* +void drawMeter(int needle) { + //5Char + O over + int i; + + for (i = 0; i < 5; i++) { + if (needle >= 5) + lcdMeter[i] = 5; //full + else if (needle > 0) + lcdMeter[i] = needle; //full + else //0 + lcdMeter[i] = 0x20; + + needle -= 5; + } + + if (needle > 0) + lcdMeter[5] = 6; + else + lcdMeter[5] = 0x20; +} +*/ +//VK2ETA meter for S.Meter, power and SWR +void drawMeter(int needle) +{ +#ifdef OPTION_SKINNYBARS + //Fill buffer with growing set of bars, up to needle value + for (int i = 0; i < 6; i++) { + if (needle > i) + lcdMeter[i / 3] = byte(i + 1); //Custom characters above + else if (i == 1 || i == 4) { + lcdMeter[i / 3] = 0x20; //blank + } + } +#else //Must be "fat" bars + //Fill buffer with growing set of bars, up to needle value + for (int i = 0; i < 6; i++) { + if (needle > i) + lcdMeter[i] = byte(i + 1); //Custom characters above + else + lcdMeter[i] = 0x20; //blank + } + if (needle > 7) { + lcdMeter[6] = byte(7); //Custom character "++" + } else if (needle > 6) { + lcdMeter[6] = 0x2B; //"+" + } else lcdMeter[6] = 0x20; +#endif //OPTION_FATBARS +} + + + char byteToChar(byte srcByte){ if (srcByte < 10) return 0x30 + srcByte;