diff --git a/ubitx_20/cat_libs.ino b/ubitx_20/cat_libs.ino index 2285d52..3ae0844 100644 --- a/ubitx_20/cat_libs.ino +++ b/ubitx_20/cat_libs.ino @@ -278,7 +278,19 @@ void WriteEEPRom(void) //for remove warning } else { - EEPROM.write(eepromStartIndex, write1Byte); + //Special Command + if (eepromStartIndex == 13131) //Magic Key + { + if (write1Byte == 0x51) //Restart + { + asm volatile (" jmp 0"); + } + } + else + { + EEPROM.write(eepromStartIndex, write1Byte); + } + Serial.write(0x77); //OK Serial.write(ACK); } diff --git a/ubitx_20/ubitx.h b/ubitx_20/ubitx.h index 5ea7620..734c4d0 100644 --- a/ubitx_20/ubitx.h +++ b/ubitx_20/ubitx.h @@ -21,21 +21,34 @@ //============================================================================== //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_LCD2004P //24 x 04 LCD (Parallel) +//#define UBITX_DISPLAY_LCD1602I_DUAL +//#define UBITX_DISPLAY_LCD2004P //24 x 04 LCD (Parallel) //#define UBITX_DISPLAY_LCD2004I //I2C type 24 x 04 LCD -#define I2C_DISPLAY_ADDRESS 0x3F //0x27 //DEFAULT, if Set I2C Address by uBITX Manager, read from EEProm +#define I2C_LCD_MASTER_ADDRESS_DEFAULT 0x3F //0x27 //DEFAULT, if Set I2C Address by uBITX Manager, read from EEProm +#define I2C_LCD_SECOND_ADDRESS_DEFAULT 0x27 //0x27 //only using Dual LCD Mode -//#define EXTEND_KEY_GROUP1 //MODE, BAND(-), BAND(+), STEP +#define EXTEND_KEY_GROUP1 //MODE, BAND(-), BAND(+), STEP //#define EXTEND_KEY_GROUP2 //Numeric (0~9), Point(.), Enter //Not supported in Version 1.0x #define ENABLE_FACTORYALIGN -#define ENABLE_ADCMONITOR //Starting with Version 1.07, you can read ADC values directly from uBITX Manager. So this function is not necessary. +//#define ENABLE_ADCMONITOR //Starting with Version 1.07, you can read ADC values directly from uBITX Manager. So this function is not necessary. + +extern byte I2C_LCD_MASTER_ADDRESS; //0x27 //if Set I2C Address by uBITX Manager, read from EEProm +extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode #define SMeterLatency 3 //1 is 0.25 sec +#ifdef UBITX_DISPLAY_LCD1602I + #define USE_I2C_LCD +#elif defined(UBITX_DISPLAY_LCD1602I_DUAL) + #define USE_I2C_LCD +#elif defined(UBITX_DISPLAY_LCD2004I) + #define USE_I2C_LCD +#endif + //============================================================================== // Hardware, Define PIN Usage //============================================================================== @@ -99,17 +112,41 @@ #define printLineF1(x) (printLineF(1, x)) #define printLineF2(x) (printLineF(0, x)) +//0x00 : None, 0x01 : MODE, 0x02:BAND+, 0x03:BAND-, 0x04:TUNE_STEP, 0x05:VFO Toggle, 0x06:SplitOn/Off, 0x07:TX/ON-OFF, 0x08:SDR Mode On / Off, 0x09:Rit Toggle #define FUNCTION_KEY_ADC 80 //MODE, BAND(-), BAND(+), STEP -#define FKEY_PRESS 120 -#define FKEY_MODE 0 -#define FKEY_BANDUP 1 -#define FKEY_BANDDOWN 2 -#define FKEY_STEP 3 +#define FKEY_PRESS 0x78 +#define FKEY_MODE 0x01 +#define FKEY_BANDUP 0x02 +#define FKEY_BANDDOWN 0x03 +#define FKEY_STEP 0x04 +#define FKEY_VFOCHANGE 0x05 +#define FKEY_SPLIT 0x06 +#define FKEY_TXOFF 0x07 +#define FKEY_SDRMODE 0x08 +#define FKEY_RIT 0x09 + +#define FKEY_ENTER 0x0A +#define FKEY_POINT 0x0B +#define FKEY_DELETE 0x0C +#define FKEY_CANCEL 0x0D + +#define FKEY_NUM0 0x10 +#define FKEY_NUM1 0x11 +#define FKEY_NUM2 0x12 +#define FKEY_NUM3 0x13 +#define FKEY_NUM4 0x14 +#define FKEY_NUM5 0x15 +#define FKEY_NUM6 0x16 +#define FKEY_NUM7 0x17 +#define FKEY_NUM8 0x18 +#define FKEY_NUM9 0x19 + +#define FKEY_TYPE_MAX 0x1F extern unsigned long frequency; extern byte WsprMSGCount; extern byte sMeterLevels[9]; -extern int KeyValues[16][2]; //ADC value Ranges for Extend Key +extern byte KeyValues[16][3]; //Set : Start Value, End Value, Key Type, 16 Set (3 * 16 = 48) 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 9ceb79a..00d509d 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -6,7 +6,7 @@ // 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_INFO F("+v1.073") #define FIRMWARE_VERSION_NUM 0x02 //1st Complete Project : 1 (Version 1.061), 2st Project : 2 /** @@ -182,30 +182,10 @@ byte line2DisplayStatus = 0; //0:Clear, 1 : menu, 1: DisplayFrom Idle, char lcdMeter[17]; byte sMeterLevels[9]; -int KeyValues[16][2]; -/*= { - {1023, 1025}, //1 - {707, 711}, //5 - {570, 574}, //9 - {493, 500}, //13 - - {932, 936}, //2 - {860, 864}, //3 - {800, 805}, //4 - - {672, 676}, //6 - {642, 646}, //7 - {616, 620}, //8 - - {552, 556}, //10 - {535, 539}, //11 - {520, 524}, //12 - - {438, 442}, //14 - {403, 407}, //15 - {378, 382} //16 -}; -*/ +byte I2C_LCD_MASTER_ADDRESS; //0x27 //if Set I2C Address by uBITX Manager, read from EEProm +byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode + +byte KeyValues[16][3]; byte isIFShift = 0; //1 = ifShift, 2 extend int ifShiftValue = 0; // @@ -422,7 +402,7 @@ void setFrequency(unsigned long f){ // Offset Frequency : 30Mhz and current Frequncy is 14.074 => 34.074Mhz moveFrequency = (f % 10000000); } - else if (sdrOption == 3) //Khzz move + else if (sdrOption == 3) //Khz move { //Offset Frequency + Khz, //Example : Offset Frequency : 30Mhz and current Frequncy is 7.080 => 30.080Mhz @@ -454,31 +434,6 @@ void setFrequency(unsigned long f){ } } - /* - if (cwMode == 0) - { - if (isUSB){ - si5351bx_setfreq(2, SECOND_OSC_USB - appliedCarrier + f); - si5351bx_setfreq(1, SECOND_OSC_USB); - } - else{ - si5351bx_setfreq(2, SECOND_OSC_LSB + appliedCarrier + f); - si5351bx_setfreq(1, SECOND_OSC_LSB); - } - } - else - { - if (cwMode == 1){ //CWL - si5351bx_setfreq(2, SECOND_OSC_LSB + appliedCarrier + f); - si5351bx_setfreq(1, SECOND_OSC_LSB); - } - else{ //CWU - si5351bx_setfreq(2, SECOND_OSC_USB - appliedCarrier + f); - si5351bx_setfreq(1, SECOND_OSC_USB); - } - } - */ - frequency = f; } @@ -630,6 +585,8 @@ void checkPTT(){ } #ifdef EXTEND_KEY_GROUP1 void checkButton(){ + char currentBandIndex = -1; + //only if the button is pressed int keyStatus = getBtnStatus(); if (keyStatus == -1) @@ -642,8 +599,69 @@ void checkButton(){ if (keyStatus == FKEY_PRESS) //Menu Key doMenu(); - else if (keyStatus <= FKEY_STEP) //EXTEND KEY GROUP #1 + else if (keyStatus <= FKEY_TYPE_MAX) //EXTEND KEY GROUP #1 { + + switch(keyStatus) + { + case FKEY_MODE : + if (cwMode == 1) + { + cwMode = 2; + } + else if (cwMode == 2) + { + cwMode = 0; + isUSB = 0; + } + else if (isUSB == 0) + { + isUSB = 1; + } + else + { + cwMode = 1; + } + break; + case FKEY_BANDUP : + case FKEY_BANDDOWN : + //Save Band Information + if (tuneTXType == 2 || tuneTXType == 3 || tuneTXType == 102 || tuneTXType == 103) { //only ham band move + currentBandIndex = getIndexHambanBbyFreq(frequency); + + if (currentBandIndex >= 0) { + saveBandFreqByIndex(frequency, modeToByte(), currentBandIndex); + } + } + setNextHamBandFreq(frequency, keyStatus == FKEY_BANDDOWN ? -1 : 1); //Prior Band + break; + + case FKEY_STEP : + if (++tuneStepIndex > 5) + tuneStepIndex = 1; + + EEPROM.put(TUNING_STEP, tuneStepIndex); + printLine2ClearAndUpdate(); + break; + + case FKEY_VFOCHANGE : + menuVfoToggle(1); //Vfo Toggle + break; + + case FKEY_SPLIT : + menuSplitOnOff(1); + break; + case FKEY_TXOFF: + menuTxOnOff(1, 0x01); + break; + case FKEY_SDRMODE : + menuSDROnOff(1); + break; + case FKEY_RIT : + menuRitToggle(1); + break; + } + /* if (keyStatus == FKEY_MODE) //Press Mode Key { if (cwMode == 1) @@ -664,10 +682,6 @@ void checkButton(){ cwMode = 1; } } - //else if (keyStatus == FKEY_BANDDOWN) //Press Mode Key - //{ - // setNextHamBandFreq(frequency, -1); //Prior Band - //} else if (keyStatus == FKEY_BANDUP || keyStatus == FKEY_BANDDOWN) //Press Mode Key { @@ -692,6 +706,28 @@ void checkButton(){ EEPROM.put(TUNING_STEP, tuneStepIndex); printLine2ClearAndUpdate(); } + + else if (keyStatus == FKEY_VFOCHANGE) + { + menuVfoToggle(1); //Vfo Toggle + } + else if (keyStatus == FKEY_SPLIT) + { + menuSplitOnOff(1); + } + else if (keyStatus == FKEY_TXOFF) + { + menuTxOnOff(1, 0x01); + } + else if (keyStatus == FKEY_SDRMODE) + { + menuSDROnOff(1); + } + else if (keyStatus == FKEY_RIT) + { + menuRitToggle(1); + } + */ FrequencyToVFO(1); SetCarrierFreq(); @@ -927,7 +963,6 @@ void initSettings(){ else keyerControl |= IAMBICB; } - EEPROM.get(COMMON_OPTION0, commonOption0); EEPROM.get(DISPLAY_OPTION1, displayOption1); @@ -939,8 +974,9 @@ void initSettings(){ //KeyValues for (byte i = 0; i < 16; i++) { - KeyValues[i][0] = EEPROM.read(EXTENDED_KEY_RANGE + (i * 2)); - KeyValues[i][1] = EEPROM.read(EXTENDED_KEY_RANGE + (i * 2) + 1); + KeyValues[i][0] = EEPROM.read(EXTENDED_KEY_RANGE + (i * 3)); //RANGE : Start Value + KeyValues[i][1] = EEPROM.read(EXTENDED_KEY_RANGE + (i * 3) + 1); //RANGE : End Value + KeyValues[i][2] = EEPROM.read(EXTENDED_KEY_RANGE + (i * 3) + 2); //KEY TYPE } //User callsign information @@ -1190,6 +1226,19 @@ void setup() //while(1); //end section of test */ + + //Load I2C LCD Address for I2C LCD + //I2C LCD Parametere +#ifdef USE_I2C_LCD + EEPROM.get(I2C_LCD_MASTER, I2C_LCD_MASTER_ADDRESS); + EEPROM.get(I2C_LCD_SECOND, I2C_LCD_SECOND_ADDRESS); + + if (I2C_LCD_MASTER_ADDRESS < 0x10 || I2C_LCD_MASTER_ADDRESS > 0xF0) + I2C_LCD_MASTER_ADDRESS = I2C_LCD_MASTER_ADDRESS_DEFAULT; + + if (I2C_LCD_SECOND_ADDRESS < 0x10 || I2C_LCD_SECOND_ADDRESS > 0xF0) + I2C_LCD_SECOND_ADDRESS = I2C_LCD_SECOND_ADDRESS_DEFAULT; +#endif //Serial.begin(9600); LCD_Init(); diff --git a/ubitx_20/ubitx_eemap.h b/ubitx_20/ubitx_eemap.h index d87a869..2bdb32d 100644 --- a/ubitx_20/ubitx_eemap.h +++ b/ubitx_20/ubitx_eemap.h @@ -50,7 +50,13 @@ // 256 ~ 1023 (EEProm Section #1) // 255 ~ 101 (EEProm Section #2) //============================================================================== -#define EXTENDED_KEY_RANGE 196 //Extended Key, KEY RANGE (MODE, BAND+, BAND-, TUNE_STEP, NUM0~NUM9, POINT, ENTER + +//0x00 : None, 0x01 : MODE, 0x02:BAND+, 0x03:BAND-, 0x04:TUNE_STEP, 0x05:VFO Toggle, 0x06:SplitOn/Off, 0x07:TX/ON-OFF, 0x08:SDR Mode On / Off, 0x09:Rit Toggle +#define EXTENDED_KEY_RANGE 140 //Extended Key => Set : Start Value, End Value, Key Type, 16 Set (3 * 16 = 48) + +#define I2C_LCD_MASTER 190 +#define I2C_LCD_SECOND 191 + #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 diff --git a/ubitx_20/ubitx_lcd_1602.ino b/ubitx_20/ubitx_lcd_1602.ino index 3162318..46e50a0 100644 --- a/ubitx_20/ubitx_lcd_1602.ino +++ b/ubitx_20/ubitx_lcd_1602.ino @@ -20,6 +20,7 @@ along with this program. If not, see . **************************************************************************/ +#include "ubitx.h" //Common Defines ********************************************************* #define LCD_CLEARDISPLAY 0x01 @@ -153,27 +154,6 @@ void LCD1602_Init() LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT); } -void LCD_Print(const char *c) -{ - for (uint8_t 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]); -} #endif //======================================================================== //End of TinyLCD Library by KD8CEC @@ -262,7 +242,7 @@ void backlight(void) { void LCD1602_Init() { //I2C Init - _Addr = I2C_DISPLAY_ADDRESS; + _Addr = I2C_LCD_MASTER_ADDRESS; _cols = 16; _rows = 2; _backlightval = LCD_NOBACKLIGHT; @@ -308,6 +288,7 @@ void LCD1602_Init() backlight(); } +/* void LCD_Print(const char *c) { for (uint8_t i = 0; i < strlen(c); i++) @@ -329,6 +310,7 @@ void LCD_CreateChar(uint8_t location, uint8_t charmap[]) for (int i=0; i<8; i++) LCD_Write(charmap[i]); } +*/ #endif //======================================================================== //End of I2CTinyLCD Library by KD8CEC @@ -347,6 +329,29 @@ void LCD_CreateChar(uint8_t location, uint8_t charmap[]) char c[30], b[30]; char printBuff[2][17]; //mirrors what is showing on the two lines of the display + +void LCD_Print(const char *c) +{ + for (uint8_t 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]); +} + void LCD_Init(void) { LCD1602_Init(); @@ -547,7 +552,7 @@ void updateDisplay() { -char line2Buffer[16]; +char line2Buffer[17]; //KD8CEC 200Hz ST //L14.150 200Hz ST //U14.150 +150khz @@ -787,7 +792,6 @@ void idle_process() if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency)) { int newSMeter; - checkCountSMeter = 0; //Reset Latency time //VK2ETA S-Meter from MAX9814 TC pin / divide 4 by KD8CEC for reduce EEPromSize newSMeter = analogRead(ANALOG_SMETER); @@ -804,6 +808,7 @@ void idle_process() } DisplayMeter(0, scaledSMeter, 14); + checkCountSMeter = 0; //Reset Latency time } //end of S-Meter } diff --git a/ubitx_20/ubitx_lcd_1602Dual.ino b/ubitx_20/ubitx_lcd_1602Dual.ino new file mode 100644 index 0000000..8c698ac --- /dev/null +++ b/ubitx_20/ubitx_lcd_1602Dual.ino @@ -0,0 +1,771 @@ +/************************************************************************* + KD8CEC's uBITX Display Routine for LCD1602 Dual LCD by KD8CEC + 1.This is the display code for the default LCD mounted in uBITX. + 2.Display related functions of uBITX. Some functions moved from uBITX_Ui. + 3.uBITX Idle time Processing + Functions that run at times that do not affect TX, CW, and CAT + It is called in 1/10 time unit. +----------------------------------------------------------------------------- + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +**************************************************************************/ +#include "ubitx.h" + +//Common Defines ********************************************************* +#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 + +// flags for backlight control +#define LCD_BACKLIGHT 0x08 +#define LCD_NOBACKLIGHT 0x00 + +//======================================================================== +//Begin of I2CTinyLCD Library for Dual LCD by KD8CEC +//======================================================================== +#ifdef UBITX_DISPLAY_LCD1602I_DUAL + +#include +/************************************************************************* + I2C Tiny LCD Library + Referecnce Source : LiquidCrystal_I2C.cpp // Based on the work by DFRobot + KD8CEC + + This source code is modified version for small program memory + from Arduino LiquidCrystal_I2C 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. + Ian KD8CEC +**************************************************************************/ +#define UBITX_DISPLAY_LCD1602_BASE + +#define En B00000100 // Enable bit +#define Rw B00000010 // Read/Write bit +#define Rs B00000001 // Register select bit + +#define LCD_Command(x) (LCD_Send(x, 0)) +#define LCD_Write(x) (LCD_Send(x, Rs)) + +uint8_t _Addr; +uint8_t _displayfunction; +uint8_t _displaycontrol; +uint8_t _displaymode; +uint8_t _numlines; +uint8_t _cols; +uint8_t _rows; +uint8_t _backlightval; + +#define printIIC(args) Wire.write(args) + +void expanderWrite(uint8_t _data) +{ + Wire.beginTransmission(_Addr); + printIIC((int)(_data) | _backlightval); + Wire.endTransmission(); +} + +void pulseEnable(uint8_t _data){ + expanderWrite(_data | En); // En high + delayMicroseconds(1); // enable pulse must be >450ns + + expanderWrite(_data & ~En); // En low + delayMicroseconds(50); // commands need > 37us to settle +} + +void write4bits(uint8_t value) +{ + expanderWrite(value); + pulseEnable(value); +} + +void LCD_Send(uint8_t value, uint8_t mode) +{ + uint8_t highnib=value&0xf0; + uint8_t lownib=(value<<4)&0xf0; + write4bits((highnib)|mode); + write4bits((lownib)|mode); +} + + +// Turn the (optional) backlight off/on +void noBacklight(void) { + _backlightval=LCD_NOBACKLIGHT; + expanderWrite(0); +} + +void backlight(void) { + _backlightval=LCD_BACKLIGHT; + expanderWrite(0); +} + +void LCD1602_Dual_Init() +{ + //I2C Init + _cols = 16; + _rows = 2; + _backlightval = LCD_NOBACKLIGHT; + Wire.begin(); + + delay(50); + + // Now we pull both RS and R/W low to begin commands + _Addr = I2C_LCD_MASTER_ADDRESS; + expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1) + _Addr = I2C_LCD_SECOND_ADDRESS; + expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1) + delay(1000); + //put the LCD into 4 bit mode + // this is according to the hitachi HD44780 datasheet + // figure 24, pg 46 + + _Addr = I2C_LCD_MASTER_ADDRESS; + // we start in 8bit mode, try to set 4 bit mode + write4bits(0x03 << 4); + delayMicroseconds(4500); // wait min 4.1ms + + // second try + write4bits(0x03 << 4); + delayMicroseconds(4500); // wait min 4.1ms + + // third go! + write4bits(0x03 << 4); + delayMicroseconds(150); + + // finally, set to 4-bit interface + write4bits(0x02 << 4); + + // 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! + delayMicroseconds(1000); // this command takes a long time! + + LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT); + + backlight(); + + + _Addr = I2C_LCD_SECOND_ADDRESS; + // we start in 8bit mode, try to set 4 bit mode + write4bits(0x03 << 4); + delayMicroseconds(4500); // wait min 4.1ms + + // second try + write4bits(0x03 << 4); + delayMicroseconds(4500); // wait min 4.1ms + + // third go! + write4bits(0x03 << 4); + delayMicroseconds(150); + + // finally, set to 4-bit interface + write4bits(0x02 << 4); + + // 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! + delayMicroseconds(1000); // this command takes a long time! + + LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT); + + backlight(); + + //Change to Default LCD (Master) + _Addr = I2C_LCD_MASTER_ADDRESS; +} + + +//======================================================================== +// 16 X 02 LCD Routines +//Begin of Display Base Routines (Init, printLine..) +//======================================================================== + +void LCD_Print(const char *c) +{ + for (uint8_t i = 0; i < strlen(c); i++) + { + if (*(c + i) == 0x00) return; + LCD_Write(*(c + i)); + } +} + +const int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; +void LCD_SetCursor(uint8_t col, uint8_t row) +{ + LCD_Command(LCD_SETDDRAMADDR | (col + row_offsets[row])); //0 : 0x00, 1 : 0x40, only for 20 x 4 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]); +} + +//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA +//#define OPTION_SKINNYBARS + +char c[30], b[30]; +char printBuff[4][20]; //mirrors what is showing on the two lines of the display + +void LCD_Init(void) +{ + LCD1602_Dual_Init(); + + _Addr = I2C_LCD_SECOND_ADDRESS; + initMeter(); //for Meter Display //when dual LCD, S.Meter on second LCD + _Addr = I2C_LCD_MASTER_ADDRESS; +} + + +// 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); + strcpy(printBuff[linenmbr], c); + + for (byte i = strlen(c); i < 20; i++) { // add white spaces until the end of the 20 characters line is reached + LCD_Write(' '); + } + } +} + +void printLineF(char linenmbr, const __FlashStringHelper *c) +{ + int i; + char tmpBuff[21]; + PGM_P p = reinterpret_cast(c); + + for (i = 0; i < 21; i++){ + unsigned char fChar = pgm_read_byte(p++); + tmpBuff[i] = fChar; + if (fChar == 0) + break; + } + + printLine(linenmbr, tmpBuff); +} + +#define LCD_MAX_COLUMN 20 +void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) { + if ((displayOption1 & 0x01) == 0x01) + linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle + + 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)); + else + break; + } + + for (byte i = lcdColumn; i < 20; i++) //Right Padding by Space + LCD_Write(' '); +} + +// short cut to print to the first line +void printLine1(const char *c) +{ + printLine(1,c); +} +// short cut to print to the first line +void printLine2(const char *c) +{ + printLine(0,c); +} + +void clearLine2() +{ + printLine2(""); + line2DisplayStatus = 0; +} + +// short cut to print to the first line +void printLine1Clear(){ + printLine(1,""); +} +// short cut to print to the first line +void printLine2Clear(){ + printLine(0, ""); +} + +void printLine2ClearAndUpdate(){ + printLine(0, ""); + line2DisplayStatus = 0; + updateDisplay(); +} + +//================================================================================== +//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 + // 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; // + + memset(c, 0, sizeof(c)); + + if (inTx){ + if (isCWAutoMode == 2) { + for (i = 0; i < 4; i++) + c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' '); + + //display Sending Index + c[4] = byteToChar(sendingCWTextIndex); + c[5] = '='; + } + else { + if (cwTimeout > 0) + strcpy(c, " CW:"); + else + strcpy(c, " TX:"); + } + } + else { + if (ritOn) + strcpy(c, "RIT "); + else { + if (cwMode == 0) + { + if (isUSB) + strcpy(c, "USB "); + else + strcpy(c, "LSB "); + } + else if (cwMode == 1) + { + strcpy(c, "CWL "); + } + else + { + strcpy(c, "CWU "); + } + } + + if (vfoActive == VFO_A) // VFO A is active + strcat(c, "A:"); + else + strcat(c, "B:"); + } + + //Fixed by Mitani Massaru (JE4SMQ) + if (isShiftDisplayCWFreq == 1) + { + if (cwMode == 1) //CWL + tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal; + else if (cwMode == 2) //CWU + tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal; + } + + //display frequency + for (int i = 15; i >= 6; i--) { + if (tmpFreq > 0) { + if (i == 12 || i == 8) c[i] = '.'; + else { + c[i] = tmpFreq % 10 + 0x30; + tmpFreq /= 10; + } + } + else + c[i] = ' '; + } + + //remarked by KD8CEC + //already RX/TX status display, and over index (16 x 2 LCD) + printLine(1, c); + + byte diplayVFOLine = 1; + if ((displayOption1 & 0x01) == 0x01) + diplayVFOLine = 0; + + if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) || + (vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) { + LCD_SetCursor(5,diplayVFOLine); + LCD_Write((uint8_t)0); + } + else if (isCWAutoMode == 2){ + LCD_SetCursor(5,diplayVFOLine); + LCD_Write(0x7E); + } + else + { + LCD_SetCursor(5,diplayVFOLine); + LCD_Write(':'); + } +} + + + +char line2Buffer[20]; +//KD8CEC 200Hz ST +//L14.150 200Hz ST +//U14.150 +150khz +int freqScrollPosition = 0; + +//Example Line2 Optinal Display +//immediate execution, not call by scheulder +//warning : unused parameter 'displayType' <-- ignore, this is reserve +void updateLine2Buffer(char displayType) +{ + unsigned long tmpFreq = 0; + if (ritOn) + { + strcpy(line2Buffer, "RitTX:"); + + //display frequency + tmpFreq = ritTxFrequency; + + //Fixed by Mitani Massaru (JE4SMQ) + if (isShiftDisplayCWFreq == 1) + { + if (cwMode == 1) //CWL + tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal; + else if (cwMode == 2) //CWU + tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal; + } + + for (int i = 15; i >= 6; i--) { + if (tmpFreq > 0) { + if (i == 12 || i == 8) line2Buffer[i] = '.'; + else { + line2Buffer[i] = tmpFreq % 10 + 0x30; + tmpFreq /= 10; + } + } + else + line2Buffer[i] = ' '; + } + + return; + } //end of ritOn display + + //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; + } + } + else + line2Buffer[i] = ' '; + } + + memset(&line2Buffer[10], ' ', 10); + + if (isIFShift) + { + line2Buffer[6] = 'M'; + line2Buffer[7] = ' '; + //IFShift Offset Value + line2Buffer[8] = 'I'; + line2Buffer[9] = 'F'; + + 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); + + for (int i = 12; i < 17; i++) + { + if (line2Buffer[i] == 0) + line2Buffer[i] = ' '; + } + } // end of display IF + else // step & Key Type display + { + //Step + long tmpStep = arTuneStep[tuneStepIndex -1]; + + byte isStepKhz = 0; + if (tmpStep >= 1000) + { + isStepKhz = 2; + } + + for (int i = 13; i >= 11 - isStepKhz; i--) { + if (tmpStep > 0) { + line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30; + tmpStep /= 10; + } + else + line2Buffer[i +isStepKhz] = ' '; + } + + if (isStepKhz == 0) + { + line2Buffer[14] = 'H'; + line2Buffer[15] = 'z'; + } + } + + //line2Buffer[17] = ' '; + /* ianlee + //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 +void DisplayMeter(byte meterType, byte meterValue, char drawPosition) +{ + if (meterType == 0 || meterType == 1 || meterType == 2) + { + drawMeter(meterValue); + + LCD_SetCursor(drawPosition, 0); + LCD_Write('S'); + + LCD_Write(':'); + for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6 + LCD_Write(lcdMeter[i]); + } +} + + +byte testValue = 0; +char checkCount = 0; + +int currentSMeter = 0; +byte scaledSMeter = 0; +char checkCountSMeter = 0; + +char beforeKeyType = -1; +char displaySDRON = 0; + +//execute interval : 0.25sec +void idle_process() +{ + //space for user graphic display + if (menuOn == 0) + { + if ((displayOption1 & 0x10) == 0x10) //always empty topline + return; + + //if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message + if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) { + if (checkCount++ > 1) + { + updateLine2Buffer(0); //call by scheduler + printLine2(line2Buffer); + line2DisplayStatus = 2; + checkCount = 0; + + //check change CW Key Type + if (beforeKeyType != cwKeyType) + { + _Addr = I2C_LCD_SECOND_ADDRESS; + LCD_SetCursor(10, 0); + LCD_Write('K'); + LCD_Write('E'); + LCD_Write('Y'); + LCD_Write(':'); + + //Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb + if (cwKeyType == 0) + { + LCD_Write('S'); + LCD_Write('T'); + } + else if (cwKeyType == 1) + { + LCD_Write('I'); + LCD_Write('A'); + } + else + { + LCD_Write('I'); + LCD_Write('B'); + } + + beforeKeyType = cwKeyType; + _Addr = I2C_LCD_MASTER_ADDRESS; + } //Display Second Screen + + } + } + + //EX for Meters + + //S-Meter Display + _Addr = I2C_LCD_SECOND_ADDRESS; + if (sdrModeOn == 1) + { + if (displaySDRON == 0) //once display + { + displaySDRON = 1; + LCD_SetCursor(0, 0); + LCD_Write('S'); + LCD_Write('D'); + LCD_Write('R'); + LCD_Write(' '); + LCD_Write('M'); + LCD_Write('O'); + LCD_Write('D'); + LCD_Write('E'); + } + } + else if (((displayOption1 & 0x08) == 0x08) && (++checkCountSMeter > 3)) + { + int newSMeter; + displaySDRON = 0; + + //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); + currentSMeter = (currentSMeter * 3 + newSMeter * 7) / 10; //remarked becaused of have already Latency time + + scaledSMeter = 0; + for (byte s = 8; s >= 1; s--) { + if (currentSMeter > sMeterLevels[s]) { + scaledSMeter = s; + break; + } + } + + DisplayMeter(0, scaledSMeter, 0); + + checkCountSMeter = 0; + } //end of S-Meter + _Addr = I2C_LCD_MASTER_ADDRESS; + + + } +} + +//AutoKey LCD Display Routine +void Display_AutoKeyTextIndex(byte textIndex) +{ + byte diplayAutoCWLine = 0; + + if ((displayOption1 & 0x01) == 0x01) + diplayAutoCWLine = 1; + LCD_SetCursor(0, diplayAutoCWLine); + LCD_Write(byteToChar(textIndex)); + LCD_Write(':'); +} + +void DisplayCallsign(byte callSignLength) +{ + _Addr = I2C_LCD_SECOND_ADDRESS; + printLineFromEEPRom(1, 16 - userCallsignLength, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) + _Addr = I2C_LCD_MASTER_ADDRESS; +} + +void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) +{ + _Addr = I2C_LCD_SECOND_ADDRESS; + printLineF(1, fwVersionInfo); + _Addr = I2C_LCD_MASTER_ADDRESS; +} + +#endif diff --git a/ubitx_20/ubitx_lcd_2004.ino b/ubitx_20/ubitx_lcd_2004.ino index 8e552a6..f895a8b 100644 --- a/ubitx_20/ubitx_lcd_2004.ino +++ b/ubitx_20/ubitx_lcd_2004.ino @@ -20,6 +20,7 @@ along with this program. If not, see . **************************************************************************/ +#include "ubitx.h" //Common Defines ********************************************************* #define LCD_CLEARDISPLAY 0x01 @@ -241,7 +242,7 @@ void backlight(void) { void LCD2004_Init() { //I2C Init - _Addr = I2C_DISPLAY_ADDRESS; + _Addr = I2C_LCD_MASTER_ADDRESS; _cols = 20; _rows = 4; _backlightval = LCD_NOBACKLIGHT; @@ -325,7 +326,7 @@ void LCD_CreateChar(uint8_t location, uint8_t charmap[]) //#define OPTION_SKINNYBARS char c[30], b[30]; -char printBuff[4][20]; //mirrors what is showing on the two lines of the display +char printBuff[4][21]; //mirrors what is showing on the two lines of the display void LCD_Init(void) { @@ -807,7 +808,7 @@ void idle_process() if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency)) { int newSMeter; - + //VK2ETA S-Meter from MAX9814 TC pin newSMeter = analogRead(ANALOG_SMETER); @@ -823,6 +824,7 @@ void idle_process() } DisplayMeter(0, scaledSMeter, 0); + checkCountSMeter = 0; //Reset Latency time } //end of S-Meter } diff --git a/ubitx_20/ubitx_menu.ino b/ubitx_20/ubitx_menu.ino index eac44b0..2af9627 100644 --- a/ubitx_20/ubitx_menu.ino +++ b/ubitx_20/ubitx_menu.ino @@ -403,15 +403,15 @@ void menuSplitOnOff(int btn){ else { if (splitOn == 1){ splitOn = 0; - //printLineF2(F("Split Off!")); - printLineF2(F("[OFF]")); + printLineF2(F("SPT Off")); + //printLineF2(F("[OFF]")); } else { splitOn = 1; if (ritOn == 1) ritOn = 0; - //printLineF2(F("Split On!")); - printLineF2(F("[ON]")); + printLineF2(F("SPT On")); + //printLineF2(F("[ON]")); } menuClearExit(500); @@ -430,11 +430,11 @@ void menuTxOnOff(int btn, byte optionType){ else { if ((isTxType & optionType) == 0){ isTxType |= optionType; - printLineF2(F("TX OFF!")); + printLineF2(F("TX OFF")); } else { isTxType &= ~(optionType); - printLineF2(F("TX ON!")); + printLineF2(F("TX ON")); } menuClearExit(500); @@ -453,7 +453,7 @@ void menuSDROnOff(int btn) else { if (sdrModeOn == 1){ sdrModeOn = 0; - printLineF2(F("[OFF]")); + printLineF2(F("SPK MODE")); } else { sdrModeOn = 1; @@ -464,7 +464,7 @@ void menuSDROnOff(int btn) if (splitOn == 1) splitOn = 0; - printLineF2(F("[ON]")); + printLineF2(F("SDR MODE")); } EEPROM.put(ENABLE_SDR, sdrModeOn); diff --git a/ubitx_20/ubitx_si5351.ino b/ubitx_20/ubitx_si5351.ino index 6587db6..2708b36 100644 --- a/ubitx_20/ubitx_si5351.ino +++ b/ubitx_20/ubitx_si5351.ino @@ -15,7 +15,6 @@ ************************************************************************************/ // ************* SI5315 routines - tks Jerry Gaffke, KE7ER *********************** - // An minimalist standalone set of Si5351 routines. // VCOA is fixed at 875mhz, VCOB not used. // The output msynth dividers are used to generate 3 independent clocks @@ -127,7 +126,9 @@ void si5351_set_calibration(int32_t cal){ void SetCarrierFreq() { unsigned long appliedCarrier = ((cwMode == 0 ? usbCarrier : cwmCarrier) + (isIFShift && (inTx == 0) ? ifShiftValue : 0)); - si5351bx_setfreq(0, (sdrModeOn ? 0 : appliedCarrier)); + //si5351bx_setfreq(0, (sdrModeOn ? 0 : appliedCarrier)); + si5351bx_setfreq(0, ((sdrModeOn && (inTx == 0)) ? 0 : appliedCarrier)); //found bug by KG4GEK + /* if (cwMode == 0) diff --git a/ubitx_20/ubitx_ui.ino b/ubitx_20/ubitx_ui.ino index faf8f53..c303daa 100644 --- a/ubitx_20/ubitx_ui.ino +++ b/ubitx_20/ubitx_ui.ino @@ -184,9 +184,12 @@ int getBtnStatus(void){ return FKEY_PRESS; else { + readButtonValue = readButtonValue / 4; + //return FKEY_VFOCHANGE; for (int i = 0; i < 16; i++) if (KeyValues[i][0] <= readButtonValue && KeyValues[i][1] >= readButtonValue) - return i; + return KeyValues[i][2]; + //return i; } return -1; diff --git a/ubitx_20/ubitx_wspr.ino b/ubitx_20/ubitx_wspr.ino index 8ac28b5..eb85147 100644 --- a/ubitx_20/ubitx_wspr.ino +++ b/ubitx_20/ubitx_wspr.ino @@ -36,7 +36,6 @@ unsigned long TX_P2; // Variable values for MSNB_P2 which defines the frequen extern int enc_read(void); byte WsprMSGCount = 0; -#define PTT (A3) #define WSPR_BAND1 401