From d72181603987234dc6d809978131f181ff6198a6 Mon Sep 17 00:00:00 2001 From: phdlee Date: Thu, 12 Apr 2018 22:08:43 +0900 Subject: [PATCH 1/4] LCD Work step1 --- ubitx_20/ubitx.h | 121 ++- ubitx_20/ubitx_20.ino | 189 +---- ubitx_20/ubitx_eemap.h | 118 +++ ubitx_20/ubitx_lcd_1602i.ino | 47 +- ubitx_20/ubitx_lcd_1602iian.ino | 753 ++++++++++++++++++ ubitx_20/ubitx_lcd_1602p.ino | 28 +- ...bitx_lcd_2404i.ino => ubitx_lcd_2004i.ino} | 0 ubitx_20/ubitx_lcd_2004p.ino | 702 ++++++++++++++++ ubitx_20/ubitx_lcd_2404p.ino | 22 - ubitx_20/ubitx_menu.ino | 32 +- ubitx_20/ubitx_wspr.ino | 9 +- 11 files changed, 1751 insertions(+), 270 deletions(-) create mode 100644 ubitx_20/ubitx_eemap.h create mode 100644 ubitx_20/ubitx_lcd_1602iian.ino rename ubitx_20/{ubitx_lcd_2404i.ino => ubitx_lcd_2004i.ino} (100%) create mode 100644 ubitx_20/ubitx_lcd_2004p.ino delete mode 100644 ubitx_20/ubitx_lcd_2404p.ino diff --git a/ubitx_20/ubitx.h b/ubitx_20/ubitx.h index 93467c38..41d35551 100644 --- a/ubitx_20/ubitx.h +++ b/ubitx_20/ubitx.h @@ -14,32 +14,58 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . **************************************************************************/ -#define WSPR_COUNT 443 //WSPR_MESSAGE_COUNT -#define WSPR_MESSAGE1 444 // -#define WSPR_MESSAGE2 490 // -#define WSPR_MESSAGE3 536 // -#define WSPR_MESSAGE4 582 // - -#define WSPR_BAND_COUNT 3 - -#define TX_SSB 0 -#define TX_CW 1 - - -extern void printLine1(const char *c); -extern void printLine2(const char *c); -extern void printLineF(char linenmbr, const __FlashStringHelper *c); -extern void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetType); -extern byte delay_background(unsigned delayTime, byte fromType); -extern int btnDown(void); -extern char c[30]; -extern char b[30]; -extern int enc_read(void); - -extern unsigned long frequency; - -#define printLineF1(x) (printLineF(1, x)) -#define printLineF2(x) (printLineF(0, x)) +#include //for Linux, On Linux it is case sensitive. + +//============================================================================== +// Compile Option +//============================================================================== +#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. + +//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_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_LCD2004I //I2C type 24 x 04 LCD + +//============================================================================== +// Hardware, Define PIN Usage +//============================================================================== +/** + * We need to carefully pick assignment of pin for various purposes. + * There are two sets of completely programmable pins on the Raduino. + * First, on the top of the board, in line with the LCD connector is an 8-pin connector + * that is largely meant for analog inputs and front-panel control. It has a regulated 5v output, + * ground and six pins. Each of these six pins can be individually programmed + * either as an analog input, a digital input or a digital output. + * The pins are assigned as follows (left to right, display facing you): + * Pin 1 (Violet), A7, SPARE + * Pin 2 (Blue), A6, KEYER (DATA) + * Pin 3 (Green), +5v + * Pin 4 (Yellow), Gnd + * Pin 5 (Orange), A3, PTT + * Pin 6 (Red), A2, F BUTTON + * Pin 7 (Brown), A1, ENC B + * Pin 8 (Black), A0, ENC A + *Note: A5, A4 are wired to the Si5351 as I2C interface + * * + * Though, this can be assigned anyway, for this application of the Arduino, we will make the following + * assignment + * A2 will connect to the PTT line, which is the usually a part of the mic connector + * A3 is connected to a push button that can momentarily ground this line. This will be used for RIT/Bandswitching, etc. + * A6 is to implement a keyer, it is reserved and not yet implemented + * A7 is connected to a center pin of good quality 100K or 10K linear potentiometer with the two other ends connected to + * ground and +5v lines available on the connector. This implments the tuning mechanism + */ +#define ENC_A (A0) +#define ENC_B (A1) +#define FBUTTON (A2) +#define PTT (A3) +#define ANALOG_KEYER (A6) +#define ANALOG_SPARE (A7) +#define ANALOG_SMETER (A7) //by KD8CEC /** @@ -51,19 +77,34 @@ extern unsigned long frequency; * - TX_RX line : Switches between Transmit and Receive after sensing the PTT or the morse keyer * - CW_KEY line : turns on the carrier for CW */ +#define TX_RX (7) //Relay +#define CW_TONE (6) +#define TX_LPF_A (5) //Relay +#define TX_LPF_B (4) //Relay +#define TX_LPF_C (3) //Relay +#define CW_KEY (2) + +//============================================================================== +// for public, Variable, functions +//============================================================================== +#define WSPR_BAND_COUNT 3 +#define TX_SSB 0 +#define TX_CW 1 +#define printLineF1(x) (printLineF(1, x)) +#define printLineF2(x) (printLineF(0, x)) -#define TX_RX (7) -#define CW_TONE (6) -#define TX_LPF_A (5) -#define TX_LPF_B (4) -#define TX_LPF_C (3) -#define CW_KEY (2) - -//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes -//these are the parameter passed to startTx -#define TX_SSB 0 -#define TX_CW 1 +extern unsigned long frequency; +extern byte WsprMSGCount; +extern void printLine1(const char *c); +extern void printLine2(const char *c); +extern void printLineF(char linenmbr, const __FlashStringHelper *c); +extern void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetType); +extern byte delay_background(unsigned delayTime, byte fromType); +extern int btnDown(void); +extern char c[30]; +extern char b[30]; +extern int enc_read(void); extern void si5351bx_init(void); extern void si5351bx_setfreq(uint8_t clknum, uint32_t fout); extern void si5351_set_calibration(int32_t cal); @@ -76,6 +117,6 @@ extern void stopTx(void); extern void setTXFilters(unsigned long freq); extern void SendWSPRManage(void); -extern byte WsprMSGCount; - - +extern char byteToChar(byte srcByte); +extern void DisplayCallsign(byte callSignLength); +extern void DisplayVersionInfo(const char* fwVersionInfo); diff --git a/ubitx_20/ubitx_20.ino b/ubitx_20/ubitx_20.ino index f3ccbf03..5b7b13ad 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -1,20 +1,7 @@ //Firmware Version -#define FIRMWARE_VERSION_INFO F("CE v1.071") +#define FIRMWARE_VERSION_INFO F("CEC v1.071") #define FIRMWARE_VERSION_NUM 0x02 //1st Complete Project : 1 (Version 1.061), 2st Project : 2 -//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_LCD1602I //I2C type 16 x 02 LCD -//#define UBITX_DISPLAY_LCD2404P //24 x 04 LCD -//#define UBITX_DISPLAY_LCD2404I //I2C type 24 x 04 LCD - -//Compile Option -#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. - - /** Cat Suppoort uBITX CEC Version Most features(TX, Frequency Range, Ham Band, TX Control, CW delay, start Delay... more) have been added by KD8CEC. @@ -56,161 +43,8 @@ #include #include #include "ubitx.h" +#include "ubitx_eemap.h" -/** - The main chip which generates upto three oscillators of various frequencies in the - Raduino is the Si5351a. To learn more about Si5351a you can download the datasheet - from www.silabs.com although, strictly speaking it is not a requirment to understand this code. - - We no longer use the standard SI5351 library because of its huge overhead due to many unused - features consuming a lot of program space. Instead of depending on an external library we now use - Jerry Gaffke's, KE7ER, lightweight standalone mimimalist "si5351bx" routines (see further down the - code). Here are some defines and declarations used by Jerry's routines: -*/ - - -/** - * We need to carefully pick assignment of pin for various purposes. - * There are two sets of completely programmable pins on the Raduino. - * First, on the top of the board, in line with the LCD connector is an 8-pin connector - * that is largely meant for analog inputs and front-panel control. It has a regulated 5v output, - * ground and six pins. Each of these six pins can be individually programmed - * either as an analog input, a digital input or a digital output. - * The pins are assigned as follows (left to right, display facing you): - * Pin 1 (Violet), A7, SPARE - * Pin 2 (Blue), A6, KEYER (DATA) - * Pin 3 (Green), +5v - * Pin 4 (Yellow), Gnd - * Pin 5 (Orange), A3, PTT - * Pin 6 (Red), A2, F BUTTON - * Pin 7 (Brown), A1, ENC B - * Pin 8 (Black), A0, ENC A - *Note: A5, A4 are wired to the Si5351 as I2C interface - * * - * Though, this can be assigned anyway, for this application of the Arduino, we will make the following - * assignment - * A2 will connect to the PTT line, which is the usually a part of the mic connector - * A3 is connected to a push button that can momentarily ground this line. This will be used for RIT/Bandswitching, etc. - * A6 is to implement a keyer, it is reserved and not yet implemented - * A7 is connected to a center pin of good quality 100K or 10K linear potentiometer with the two other ends connected to - * ground and +5v lines available on the connector. This implments the tuning mechanism - */ - -#define ENC_A (A0) -#define ENC_B (A1) -#define FBUTTON (A2) -#define PTT (A3) -#define ANALOG_KEYER (A6) -#define ANALOG_SPARE (A7) -#define ANALOG_SMETER (A7) //by KD8CEC - -/** - * The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory. - * We have to be very careful with variables that are declared inside the functions as they are - * created in a memory region called the stack. The stack has just a few bytes of space on the Arduino - * if you declare large strings inside functions, they can easily exceed the capacity of the stack - * and mess up your programs. - * We circumvent this by declaring a few global buffers as kitchen counters where we can - * slice and dice our strings. These strings are mostly used to control the display or handle - * the input and output from the USB port. We must keep a count of the bytes used while reading - * the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable. - */ -int count = 0; //to generally count ticks, loops, etc - -/** - * The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig. - * This assignment is as follows : - * Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - * GND +5V CLK0 GND GND CLK1 GND GND CLK2 GND D2 D3 D4 D5 D6 D7 - * These too are flexible with what you may do with them, for the Raduino, we use them to : - * - TX_RX line : Switches between Transmit and Receive after sensing the PTT or the morse keyer - * - CW_KEY line : turns on the carrier for CW - */ - -#define TX_RX (7) -#define CW_TONE (6) -#define TX_LPF_A (5) -#define TX_LPF_B (4) -#define TX_LPF_C (3) -#define CW_KEY (2) - -/** - * These are the indices where these user changable settinngs are stored in the EEPROM - */ -#define MASTER_CAL 0 -#define LSB_CAL 4 -#define USB_CAL 8 -#define SIDE_TONE 12 -//these are ids of the vfos as well as their offset into the eeprom storage, don't change these 'magic' values -#define VFO_A 16 -#define VFO_B 20 -#define CW_SIDETONE 24 -#define CW_SPEED 28 - -//KD8CEC EEPROM MAP -#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 -#define SDR_FREQUNCY 243 - -#define CW_CAL 252 -#define VFO_A_MODE 256 -#define VFO_B_MODE 257 -#define CW_DELAY 258 -#define CW_START 259 -#define HAM_BAND_COUNT 260 // -#define TX_TUNE_TYPE 261 // -#define HAM_BAND_RANGE 262 //FROM (2BYTE) TO (2BYTE) * 10 = 40byte -#define HAM_BAND_FREQS 302 //40, 1 BAND = 4Byte most bit is mode -#define TUNING_STEP 342 //TUNING STEP * 6 (index 1 + STEPS 5) //1STEP : - - -//for reduce cw key error, eeprom address -#define CW_ADC_MOST_BIT1 348 //most 2bits of DOT_TO , DOT_FROM, ST_TO, ST_FROM -#define CW_ADC_ST_FROM 349 //CW ADC Range STRAIGHT KEY from (Lower 8 bit) -#define CW_ADC_ST_TO 350 //CW ADC Range STRAIGHT KEY to (Lower 8 bit) -#define CW_ADC_DOT_FROM 351 //CW ADC Range DOT from (Lower 8 bit) -#define CW_ADC_DOT_TO 352 //CW ADC Range DOT to (Lower 8 bit) - -#define CW_ADC_MOST_BIT2 353 //most 2bits of BOTH_TO, BOTH_FROM, DASH_TO, DASH_FROM -#define CW_ADC_DASH_FROM 354 //CW ADC Range DASH from (Lower 8 bit) -#define CW_ADC_DASH_TO 355 //CW ADC Range DASH to (Lower 8 bit) -#define CW_ADC_BOTH_FROM 356 //CW ADC Range BOTH from (Lower 8 bit) -#define CW_ADC_BOTH_TO 357 //CW ADC Range BOTH to (Lower 8 bit) -#define CW_KEY_TYPE 358 -#define CW_DISPLAY_SHIFT 359 //Transmits on CWL, CWU Mode, LCD Frequency shifts Sidetone Frequency. - //(7:Enable / Disable //0: enable, 1:disable, (default is applied shift) - //6 : 0 : Adjust Pulus, 1 : Adjust Minus - //0~5: Adjust Value : * 10 = Adjust Value (0~300) -#define COMMON_OPTION0 360 //0: Confirm : CW Frequency Shift - //1 : IF Shift Save - // - // - // -#define IF_SHIFTVALUE 363 - -#define DISPLAY_OPTION1 361 //Display Option1 -#define DISPLAY_OPTION2 362 //Display Option2 - -#define CHANNEL_FREQ 630 //Channel 1 ~ 20, 1 Channel = 4 bytes -#define CHANNEL_DESC 710 //Channel 1 ~ 20, 1 Channel = 4 bytes -#define RESERVE3 770 //Reserve3 between Channel and Firmware id check - -//Check Firmware type and version -#define FIRMWAR_ID_ADDR 776 //776 : 0x59, 777 :0x58, 778 : 0x68 : Id Number, if not found id, erase eeprom(32~1023) for prevent system error. -#define VERSION_ADDRESS 779 //check Firmware version -//USER INFORMATION -#define USER_CALLSIGN_KEY 780 //0x59 -#define USER_CALLSIGN_LEN 781 //1BYTE (OPTION + LENGTH) + CALLSIGN (MAXIMUM 18) -#define USER_CALLSIGN_DAT 782 //CALL SIGN DATA //direct EEPROM to LCD basic offset - -//AUTO KEY STRUCTURE -//AUTO KEY USE 800 ~ 1023 -#define CW_AUTO_MAGIC_KEY 800 //0x73 -#define CW_AUTO_COUNT 801 //0 ~ 255 -#define CW_AUTO_DATA 803 //[INDEX, INDEX, INDEX,DATA,DATA, DATA (Positon offset is CW_AUTO_DATA -#define CW_DATA_OFSTADJ CW_AUTO_DATA - USER_CALLSIGN_DAT //offset adjust for ditect eeprom to lcd (basic offset is USER_CALLSIGN_DAT -#define CW_STATION_LEN 1023 //value range : 4 ~ 30 /** * The uBITX is an upconnversion transceiver. The first IF is at 45 MHz. * The first IF frequency is not exactly at 45 Mhz but about 5 khz lower, @@ -242,11 +76,6 @@ int count = 0; //to generally count ticks, loops, etc #define LOWEST_FREQ_DIAL (3000l) #define HIGHEST_FREQ_DIAL (60000000l) -//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes -//these are the parameter passed to startTx -#define TX_SSB 0 -#define TX_CW 1 - char ritOn = 0; char vfoActive = VFO_A; int8_t meter_reading = 0; // a -1 on meter makes it invisible @@ -338,7 +167,7 @@ byte advancedFreqOption1; //255 : Bit0: use IFTune_Value, Bit1 : use Stored byte attLevel = 0; //ATT : RF Gain Control (Receive) <-- IF1 Shift, 0 : Off, ShiftValue is attLevel * 100; attLevel 150 = 15K byte if1TuneValue = 0; //0 : OFF, IF1 + if1TuneValue * 100; // + - 12500; byte sdrModeOn = 0; //SDR MODE ON / OFF -unsigned long SDR_Center_Freq; //DEFAULT Frequency : 32000000 +unsigned long SDR_Center_Freq; // unsigned long beforeIdle_ProcessTime = 0; //for check Idle time byte line2DisplayStatus = 0; //0:Clear, 1 : menu, 1: DisplayFrom Idle, @@ -1114,8 +943,8 @@ void initSettings(){ } EEPROM.get(SDR_FREQUNCY, SDR_Center_Freq); - if (SDR_Center_Freq == 0) - SDR_Center_Freq = 32000000; + //if (SDR_Center_Freq == 0) + // SDR_Center_Freq = 32000000; //default Value (for original hardware) if (cwAdcSTFrom >= cwAdcSTTo) @@ -1240,15 +1069,17 @@ void setup() //Serial.begin(9600); LCD_Init(); - printLineF(1, FIRMWARE_VERSION_INFO); + //printLineF(1, FIRMWARE_VERSION_INFO); + DisplayVersionInfo(FIRMWARE_VERSION_INFO); Init_Cat(38400, SERIAL_8N1); initSettings(); if (userCallsignLength > 0 && ((userCallsignLength & 0x80) == 0x80)) { userCallsignLength = userCallsignLength & 0x7F; - printLineFromEEPRom(0, 0, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) - delay(500); + //printLineFromEEPRom(0, 0, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) + //delay(500); + DisplayCallsign(userCallsignLength); } else { printLineF(0, F("uBITX v0.20")); diff --git a/ubitx_20/ubitx_eemap.h b/ubitx_20/ubitx_eemap.h new file mode 100644 index 00000000..dc104872 --- /dev/null +++ b/ubitx_20/ubitx_eemap.h @@ -0,0 +1,118 @@ +/************************************************************************* + header file for EEProm Address Map by KD8CEC + It must be protected to protect the factory calibrated calibration. +----------------------------------------------------------------------------- + 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 . +**************************************************************************/ +//============================================================================== +// Factory-shipped EEProm address +// (factory Firmware) +// Address : 0 ~ 31 +//============================================================================== +#define MASTER_CAL 0 +#define LSB_CAL 4 +#define USB_CAL 8 +#define SIDE_TONE 12 +//these are ids of the vfos as well as their offset into the eeprom storage, don't change these 'magic' values +#define VFO_A 16 +#define VFO_B 20 +#define CW_SIDETONE 24 +#define CW_SPEED 28 + +//============================================================================== +// The spare space available in the original firmware #1 +// Address : 32 ~ 63 +//============================================================================== +#define RESERVE_FOR_FACTORY1 32 + +//============================================================================== +// The spare space available in the original firmware #2 +// (Enabled if the EEProm address is insufficient) +// Address : 64 ~ 100 +//============================================================================== +#define RESERVE_FOR_FACTORY2 64 + +//============================================================================== +// KD8CEC EEPROM MAP +// Address : 101 ~ 1023 +// 256 is the base address +// 256 ~ 1023 (EEProm Section #1) +// 255 ~ 101 (EEProm Section #2) +//============================================================================== +#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 +#define SDR_FREQUNCY 243 +#define CW_CAL 252 + +#define VFO_A_MODE 256 +#define VFO_B_MODE 257 +#define CW_DELAY 258 +#define CW_START 259 +#define HAM_BAND_COUNT 260 // +#define TX_TUNE_TYPE 261 // +#define HAM_BAND_RANGE 262 //FROM (2BYTE) TO (2BYTE) * 10 = 40byte +#define HAM_BAND_FREQS 302 //40, 1 BAND = 4Byte most bit is mode +#define TUNING_STEP 342 //TUNING STEP * 6 (index 1 + STEPS 5) //1STEP : + +//for reduce cw key error, eeprom address +#define CW_ADC_MOST_BIT1 348 //most 2bits of DOT_TO , DOT_FROM, ST_TO, ST_FROM +#define CW_ADC_ST_FROM 349 //CW ADC Range STRAIGHT KEY from (Lower 8 bit) +#define CW_ADC_ST_TO 350 //CW ADC Range STRAIGHT KEY to (Lower 8 bit) +#define CW_ADC_DOT_FROM 351 //CW ADC Range DOT from (Lower 8 bit) +#define CW_ADC_DOT_TO 352 //CW ADC Range DOT to (Lower 8 bit) + +#define CW_ADC_MOST_BIT2 353 //most 2bits of BOTH_TO, BOTH_FROM, DASH_TO, DASH_FROM +#define CW_ADC_DASH_FROM 354 //CW ADC Range DASH from (Lower 8 bit) +#define CW_ADC_DASH_TO 355 //CW ADC Range DASH to (Lower 8 bit) +#define CW_ADC_BOTH_FROM 356 //CW ADC Range BOTH from (Lower 8 bit) +#define CW_ADC_BOTH_TO 357 //CW ADC Range BOTH to (Lower 8 bit) +#define CW_KEY_TYPE 358 +#define CW_DISPLAY_SHIFT 359 //Transmits on CWL, CWU Mode, LCD Frequency shifts Sidetone Frequency. + //(7:Enable / Disable //0: enable, 1:disable, (default is applied shift) + //6 : 0 : Adjust Pulus, 1 : Adjust Minus + //0~5: Adjust Value : * 10 = Adjust Value (0~300) +#define COMMON_OPTION0 360 //0: Confirm : CW Frequency Shift + //1 : IF Shift Save +#define IF_SHIFTVALUE 363 + +#define DISPLAY_OPTION1 361 //Display Option1 +#define DISPLAY_OPTION2 362 //Display Option2 + +#define WSPR_COUNT 443 //WSPR_MESSAGE_COUNT +#define WSPR_MESSAGE1 444 // +#define WSPR_MESSAGE2 490 // +#define WSPR_MESSAGE3 536 // +#define WSPR_MESSAGE4 582 // + +#define CHANNEL_FREQ 630 //Channel 1 ~ 20, 1 Channel = 4 bytes +#define CHANNEL_DESC 710 //Channel 1 ~ 20, 1 Channel = 4 bytes +#define RESERVE3 770 //Reserve3 between Channel and Firmware id check + +//Check Firmware type and version +#define FIRMWAR_ID_ADDR 776 //776 : 0x59, 777 :0x58, 778 : 0x68 : Id Number, if not found id, erase eeprom(32~1023) for prevent system error. +#define VERSION_ADDRESS 779 //check Firmware version +//USER INFORMATION +#define USER_CALLSIGN_KEY 780 //0x59 +#define USER_CALLSIGN_LEN 781 //1BYTE (OPTION + LENGTH) + CALLSIGN (MAXIMUM 18) +#define USER_CALLSIGN_DAT 782 //CALL SIGN DATA //direct EEPROM to LCD basic offset + +//AUTO KEY STRUCTURE +//AUTO KEY USE 800 ~ 1023 +#define CW_AUTO_MAGIC_KEY 800 //0x73 +#define CW_AUTO_COUNT 801 //0 ~ 255 +#define CW_AUTO_DATA 803 //[INDEX, INDEX, INDEX,DATA,DATA, DATA (Positon offset is CW_AUTO_DATA +#define CW_DATA_OFSTADJ CW_AUTO_DATA - USER_CALLSIGN_DAT //offset adjust for ditect eeprom to lcd (basic offset is USER_CALLSIGN_DAT +#define CW_STATION_LEN 1023 //value range : 4 ~ 30 + diff --git a/ubitx_20/ubitx_lcd_1602i.ino b/ubitx_20/ubitx_lcd_1602i.ino index c8546f07..21def44e 100644 --- a/ubitx_20/ubitx_lcd_1602i.ino +++ b/ubitx_20/ubitx_lcd_1602i.ino @@ -27,9 +27,27 @@ //======================================================================== //Begin of LCD Hardware define +//The I2C LCD I ordered did not arrive yet. +//I referenced the I2C LCD control in the thread at the link below. +////https://groups.io/g/BITX20/topic/variation_on_ian_s_kd8cec/16657839?p=,,,20,0,0,0::recentpostdate%2Fsticky,,,20,2,0,16657839 +//In particular, I referenced the sample code of John (VK2ETA) and K9HZ. Jack, W8TEE, Nick //======================================================================== -#include -LiquidCrystal lcd(8,9,10,11,12,13); +//#include +//LiquidCrystal lcd(8,9,10,11,12,13); + +//K9HZ's Code +//#include +//LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // + +//Jack(W8TEE) Code +//LiquidCrystal_I2C lcd(0x3F); // I2C address + +//John(VK2ETA) Code +#include +#define I2C_DISPLAY_ADDRESS 0x27 +LiquidCrystal_I2C lcd(I2C_DISPLAY_ADDRESS,16,2); // set the LCD as a 16 chars and 2 line display + +//LiquidCrystal_I2C lcd(0x27,16,2) //======================================================================== @@ -337,6 +355,16 @@ void updateLine2Buffer(char displayType) //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] = '.'; @@ -537,16 +565,27 @@ void idle_process() } } -void Display_AutoKeyTextIndex(char textIndex) +void Display_AutoKeyTextIndex(byte textIndex) { byte diplayAutoCWLine = 0; if ((displayOption1 & 0x01) == 0x01) diplayAutoCWLine = 1; lcd.setCursor(0, diplayAutoCWLine); - lcd.write(byteToChar(selectedCWTextIndex)); + lcd.write(byteToChar(textIndex)); lcd.write(':'); } +void DisplayCallsign(byte callSignLength) +{ + printLineFromEEPRom(0, 0, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) + //delay(500); +} + +void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) +{ + printLineF(1, fwVersionInfo); +} + #endif diff --git a/ubitx_20/ubitx_lcd_1602iian.ino b/ubitx_20/ubitx_lcd_1602iian.ino new file mode 100644 index 00000000..9d11bb45 --- /dev/null +++ b/ubitx_20/ubitx_lcd_1602iian.ino @@ -0,0 +1,753 @@ +/************************************************************************* + KD8CEC's uBITX Display Routine for LCD1602 Parrel + 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 . + +**************************************************************************/ +#ifdef UBITX_DISPLAY_LCD1602I_CUST +#include + +//======================================================================== +//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. + Ian KD8CEC +**************************************************************************/ +#define I2C_DISPLAY_ADDRESS 0x27 + +#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)) + +//Define connected PIN +//#define LCD_PIN_RS 8 +//#define LCD_PIN_EN 9 +//uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13}; + +uint8_t _Addr; +uint8_t _displayfunction; +uint8_t _displaycontrol; +uint8_t _displaymode; +uint8_t _numlines; +uint8_t _cols; +uint8_t _rows; +uint8_t _backlightval; + +// 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 + +// flags for backlight control +#define LCD_BACKLIGHT 0x08 +#define LCD_NOBACKLIGHT 0x00 + +#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); +} + +void LCD1602_Init() +{ + //I2C Init + _Addr; + _cols = 16; + _rows = 2; + _backlightval = LCD_NOBACKLIGHT; + Wire.begin(); + + delay(50); + + // Now we pull both RS and R/W low to begin commands + 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 + + // 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); +} + +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]); +} +//======================================================================== +//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 + +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) + 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 < 16; i++) { // add white spaces until the end of the 16 characters line is reached + LCD_Write(' '); + } + } +} + +void printLineF(char linenmbr, const __FlashStringHelper *c) +{ + int i; + char tmpBuff[17]; + PGM_P p = reinterpret_cast(c); + + for (i = 0; i < 17; i++){ + unsigned char fChar = pgm_read_byte(p++); + tmpBuff[i] = fChar; + if (fChar == 0) + break; + } + + printLine(linenmbr, tmpBuff); +} + +#define LCD_MAX_COLUMN 16 +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 < 16; 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 + 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) + //if (inTx) + // strcat(c, " TX"); + 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[16]; +//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] = ' '; + } + + //EXAMPLE #1 + if ((displayOption1 & 0x04) == 0x00) //none scroll display + line2Buffer[6] = 'k'; + else + { + //example #2 + if (freqScrollPosition++ > 18) //none scroll display time + { + line2Buffer[6] = 'k'; + if (freqScrollPosition > 25) + freqScrollPosition = -1; + } + else //scroll frequency + { + line2Buffer[10] = 'H'; + line2Buffer[11] = 'z'; + + if (freqScrollPosition < 7) + { + for (int i = 11; i >= 0; i--) + if (i - (7 - freqScrollPosition) >= 0) + line2Buffer[i] = line2Buffer[i - (7 - freqScrollPosition)]; + else + line2Buffer[i] = ' '; + } + else + { + for (int i = 0; i < 11; i++) + if (i + (freqScrollPosition - 7) <= 11) + line2Buffer[i] = line2Buffer[i + (freqScrollPosition - 7)]; + else + line2Buffer[i] = ' '; + } + } + } //scroll + + line2Buffer[7] = ' '; + + if (isIFShift) + { +// if (isDirectCall == 1) +// for (int i = 0; i < 16; i++) +// line2Buffer[i] = ' '; + + //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); + + //if (isDirectCall == 1) //if call by encoder (not scheduler), immediate print value + printLine2(line2Buffer); + } // end of display IF + else // step & Key Type display + { + //if (isDirectCall != 0) + // return; + + memset(&line2Buffer[8], ' ', 8); + //Step + long tmpStep = arTuneStep[tuneStepIndex -1]; + + byte isStepKhz = 0; + if (tmpStep >= 1000) + { + isStepKhz = 2; + } + + for (int i = 10; i >= 8 - isStepKhz; i--) { + if (tmpStep > 0) { + line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30; + tmpStep /= 10; + } + else + line2Buffer[i +isStepKhz] = ' '; + } + + if (isStepKhz == 0) + { + line2Buffer[11] = 'H'; + line2Buffer[12] = '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'; + } + } +} + +//meterType : 0 = S.Meter, 1 : P.Meter +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; + + LCD_SetCursor(drawPosition, lineNumber); + + for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6 + LCD_Write(lcdMeter[i]); + } +} + +byte testValue = 0; +char checkCount = 0; +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; + } + + //EX for Meters + /* + DisplayMeter(0, testValue++, 7); + if (testValue > 30) + testValue = 0; + */ + } + } +} + +//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) +{ + printLineFromEEPRom(0, 0, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) + //delay(500); +} + +void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) +{ + printLineF(1, fwVersionInfo); +} + + +#endif diff --git a/ubitx_20/ubitx_lcd_1602p.ino b/ubitx_20/ubitx_lcd_1602p.ino index 607d070e..b20cba50 100644 --- a/ubitx_20/ubitx_lcd_1602p.ino +++ b/ubitx_20/ubitx_lcd_1602p.ino @@ -148,7 +148,7 @@ void LCD1602_Init() void LCD_Print(const char *c) { - for (int i = 0; i < strlen(c); i++) + for (uint8_t i = 0; i < strlen(c); i++) { if (*(c + i) == 0x00) return; LCD_Write(*(c + i)); @@ -469,8 +469,10 @@ char line2Buffer[16]; //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; @@ -480,6 +482,16 @@ void updateLine2Buffer(char displayType) //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] = '.'; @@ -679,16 +691,26 @@ void idle_process() } //AutoKey LCD Display Routine -void Display_AutoKeyTextIndex(char textIndex) +void Display_AutoKeyTextIndex(byte textIndex) { byte diplayAutoCWLine = 0; if ((displayOption1 & 0x01) == 0x01) diplayAutoCWLine = 1; LCD_SetCursor(0, diplayAutoCWLine); - LCD_Write(byteToChar(selectedCWTextIndex)); + LCD_Write(byteToChar(textIndex)); LCD_Write(':'); } +void DisplayCallsign(byte callSignLength) +{ + printLineFromEEPRom(0, 0, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) + //delay(500); +} + +void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) +{ + printLineF(1, fwVersionInfo); +} #endif diff --git a/ubitx_20/ubitx_lcd_2404i.ino b/ubitx_20/ubitx_lcd_2004i.ino similarity index 100% rename from ubitx_20/ubitx_lcd_2404i.ino rename to ubitx_20/ubitx_lcd_2004i.ino diff --git a/ubitx_20/ubitx_lcd_2004p.ino b/ubitx_20/ubitx_lcd_2004p.ino new file mode 100644 index 00000000..7cec5006 --- /dev/null +++ b/ubitx_20/ubitx_lcd_2004p.ino @@ -0,0 +1,702 @@ +/************************************************************************* + KD8CEC's uBITX Display Routine for LCD2004 Parrel + 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 . + +**************************************************************************/ +#ifdef UBITX_DISPLAY_LCD2004P + + +//======================================================================== +//Begin of TinyLCD Library by KD8CEC +//======================================================================== +/************************************************************************* + LCD2004TINY Library for 20 x 4 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 LCD2004_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 (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]); +} +//======================================================================== +//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[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) { + 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[20]; + PGM_P p = reinterpret_cast(c); + + for (i = 0; i < 17; 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(2,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(2,""); +} +// 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 + 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 (20 x 4 LCD) + //if (inTx) + // strcat(c, " TX"); + + c[16] = ' '; + c[17] = 'H'; + c[18] = 'z'; + + printLine(2, c); + + byte diplayVFOLine = 2; + 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) +{ + //Second Frequency Display + 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 + else + { + + //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] = ' '; + } + + + 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] = ' '; + + //IFShift Offset Value + line2Buffer[12] = 'I'; + line2Buffer[13] = 'F'; + + line2Buffer[14] = ifShiftValue >= 0 ? '+' : 0; + line2Buffer[15] = 0; + line2Buffer[16] = ' '; + + //15, 16, 17, 18, 19 + memset(b, 0, sizeof(b)); + ltoa(ifShiftValue, b, DEC); + strncat(line2Buffer, b, 5); + } //end of else + + printLine(1, line2Buffer); + + memset(line2Buffer, ' ', 20); + { + //if (isDirectCall != 0) + // return; + + memset(&line2Buffer[8], ' ', 8); + //Step + long tmpStep = arTuneStep[tuneStepIndex -1]; + + byte isStepKhz = 0; + if (tmpStep >= 1000) + { + isStepKhz = 2; + } + + for (int i = 10; i >= 8 - isStepKhz; i--) { + if (tmpStep > 0) { + line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30; + tmpStep /= 10; + } + else + line2Buffer[i +isStepKhz] = ' '; + } + + if (isStepKhz == 0) + { + line2Buffer[11] = 'H'; + line2Buffer[12] = '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'; + } + } +} + +//meterType : 0 = S.Meter, 1 : P.Meter +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; + + LCD_SetCursor(drawPosition, lineNumber); + + for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6 + LCD_Write(lcdMeter[i]); + } +} + +byte testValue = 0; +char checkCount = 0; +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; + } + + //EX for Meters + /* + DisplayMeter(0, testValue++, 7); + if (testValue > 30) + testValue = 0; + */ + } + } +} + +//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) +{ + printLineFromEEPRom(3, 12, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) + //delay(500); +} + +void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) +{ + printLineF(3, fwVersionInfo); +} + + +#endif diff --git a/ubitx_20/ubitx_lcd_2404p.ino b/ubitx_20/ubitx_lcd_2404p.ino deleted file mode 100644 index 66c98689..00000000 --- a/ubitx_20/ubitx_lcd_2404p.ino +++ /dev/null @@ -1,22 +0,0 @@ -/************************************************************************* - KD8CEC's uBITX Display Routine for LCD2404 Parrel - 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 . - -**************************************************************************/ - - diff --git a/ubitx_20/ubitx_menu.ino b/ubitx_20/ubitx_menu.ino index 094e594d..bddaea64 100644 --- a/ubitx_20/ubitx_menu.ino +++ b/ubitx_20/ubitx_menu.ino @@ -2,11 +2,11 @@ This source code started with Farhan's original source. The license rules are followed as well. Calibration related functions kept the original source except for the minor ones. The part is collected in the last minute of this source. - Ian KD8CEC */ #include "ubitx.h" +#include "ubitx_eemap.h" //Current Frequency and mode to active VFO by KD8CEC void FrequencyToVFO(byte isSaveFreq) @@ -471,6 +471,7 @@ void menuSDROnOff(int btn) EEPROM.put(ENABLE_SDR, sdrModeOn); setFrequency(frequency); + SetCarrierFreq(); menuClearExit(500); } } @@ -589,7 +590,6 @@ int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnob { int knob; int moveDetectStep = 0; - int negativeSensitivity; char isInitDisplay = 1; delay_background(300, 0); //Default Delay @@ -679,7 +679,6 @@ int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnob } void menuCWSpeed(int btn){ - int knob = 0; int wpm; wpm = 1200/cwSpeed; @@ -732,15 +731,14 @@ void menuCWSpeed(int btn){ //Modified by KD8CEC void menuSetupCwTone(int btn){ - int knob = 0; - int prev_sideTone; + //int prev_sideTone; if (!btn){ printLineF2(F("Change CW Tone")); return; } - prev_sideTone = sideTone; + //prev_sideTone = sideTone; //printLineF1(F("Tune CW tone")); //printLineF2(F("PTT to confirm.")); //printLineF1(F("Press to set WPM")); @@ -789,7 +787,7 @@ void menuSetupCwTone(int btn){ //Modified by KD8CEC void menuSetupCwDelay(int btn){ - int knob = 0; + //int knob = 0; int tmpCWDelay = cwDelayTime * 10; if (!btn){ @@ -839,8 +837,8 @@ void menuSetupCwDelay(int btn){ //CW Time delay by KD8CEC void menuSetupTXCWInterval(int btn){ - char needDisplayInformation = 1; - int knob = 0; + //char needDisplayInformation = 1; + //int knob = 0; int tmpTXCWInterval = delayBeforeCWStartTime * 2; if (!btn){ @@ -892,8 +890,8 @@ void menuSetupTXCWInterval(int btn){ //IF Shift function, BFO Change like RIT, by KD8CEC void menuIFSSetup(int btn){ - int knob = 0; - char needApplyChangeValue = 1; + //int knob = 0; + //char needApplyChangeValue = 1; if (!btn){ if (isIFShift == 1) @@ -953,8 +951,8 @@ void menuIFSSetup(int btn){ //ATT SETUP (IF1(45MHZ) SHIFT), by KD8CEC void menuATTSetup(int btn){ - int knob = 0; - char needApplyChangeValue = 1; + //int knob = 0; + //char needApplyChangeValue = 1; if (!btn){ if (attLevel != 0) @@ -979,10 +977,10 @@ void menuATTSetup(int btn){ //Functions for CWL and CWU by KD8CEC void menuSelectMode(int btn){ - int knob = 0; + //int knob = 0; int selectModeType = 0; int beforeMode = 0; - int moveStep = 0; + //int moveStep = 0; if (!btn){ printLineF2(F("Select Mode?")); @@ -1064,9 +1062,9 @@ void menuSelectMode(int btn){ //Select CW Key Type by KD8CEC void menuSetupKeyType(int btn){ - int knob = 0; + //int knob = 0; int selectedKeyType = 0; - int moveStep = 0; + //int moveStep = 0; if (!btn){ printLineF2(F("Change Key Type?")); } diff --git a/ubitx_20/ubitx_wspr.ino b/ubitx_20/ubitx_wspr.ino index 4352413e..8ac28b51 100644 --- a/ubitx_20/ubitx_wspr.ino +++ b/ubitx_20/ubitx_wspr.ino @@ -23,14 +23,13 @@ Beta Tester : along with this program. If not, see . **********************************************************************************/ -#include #include #include "ubitx.h" //begin of test byte WsprToneCode[164]; -long lastTime=0; +unsigned long lastTime=0; unsigned long TX_MSNB_P2; // Si5351 register MSNB_P2 PLLB for Tx unsigned long TX_P2; // Variable values for MSNB_P2 which defines the frequencies for the data @@ -48,7 +47,7 @@ void SendWSPRManage() { int knob = 0; byte knobPosition = 0; - char isNeedDisplayInfo = 0; + //char isNeedDisplayInfo = 0; char nowSelectedIndex = 0; char nowWsprStep = 0; //0 : select Message, 1 : select band, 2 : send char selectedWsprMessageIndex = -1; @@ -56,8 +55,8 @@ void SendWSPRManage() unsigned long WsprTXFreq = 0; unsigned int WsprMultiChan = 0; - unsigned long prevFreq; - char loopIndex; + //unsigned long prevFreq; + byte loopIndex; delay_background(500, 0); From 0e245fc488ceb3aa27059971a3d27632ecc1934a Mon Sep 17 00:00:00 2001 From: phdlee Date: Mon, 16 Apr 2018 23:56:32 +0900 Subject: [PATCH 2/4] Add 20x04LCD and S.Meter --- ubitx_20/ubitx.h | 5 +- ubitx_20/ubitx_20.ino | 21 +- ubitx_20/ubitx_eemap.h | 3 + ubitx_20/ubitx_lcd_1602i.ino | 4 +- ubitx_20/ubitx_lcd_1602iian.ino | 4 +- ubitx_20/ubitx_lcd_1602p.ino | 133 ++++------- ubitx_20/ubitx_lcd_2004p.ino | 389 ++++++++++++++++---------------- ubitx_20/ubitx_menu.ino | 2 - ubitx_20/ubitx_ui.ino | 147 ++++++++++++ 9 files changed, 416 insertions(+), 292 deletions(-) diff --git a/ubitx_20/ubitx.h b/ubitx_20/ubitx.h index 41d35551..51bdf197 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 5b7b13ad..b80245e4 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 dc104872..56855c8b 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 21def44e..2fbfd87c 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 9d11bb45..05123395 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 b20cba50..8b2f82ba 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 7cec5006..fb29ec00 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) - { - 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:"); + //other VFO display + if (vfoActive == VFO_B) + { + tmpFreq = vfoA; + } + else + { + tmpFreq = vfoB; + } - if (sdrModeOn == 0) - { - line2Buffer[9] = 'P'; - line2Buffer[10] = 'K'; + // 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[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[14] = ifShiftValue >= 0 ? '+' : 0; - line2Buffer[15] = 0; - line2Buffer[16] = ' '; + line2Buffer[8] = 'I'; + line2Buffer[9] = 'F'; - //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[17] = ' '; - 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'; - } + //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 bddaea64..eac44b00 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 49072823..e2fad8d8 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; From f600c185412bca98e752c94efcd623b5a0a7f1b0 Mon Sep 17 00:00:00 2001 From: phdlee Date: Tue, 17 Apr 2018 21:26:29 +0900 Subject: [PATCH 3/4] add extended Keys (mode, band, tunestep) and i2clcd working --- ubitx_20/ubitx.h | 15 ++++- ubitx_20/ubitx_20.ino | 113 +++++++++++++++++++++++++++++++- ubitx_20/ubitx_eemap.h | 2 +- ubitx_20/ubitx_lcd_1602i.ino | 91 ++----------------------- ubitx_20/ubitx_lcd_1602iian.ino | 98 +++++---------------------- ubitx_20/ubitx_ui.ino | 25 +++++++ 6 files changed, 173 insertions(+), 171 deletions(-) diff --git a/ubitx_20/ubitx.h b/ubitx_20/ubitx.h index 51bdf197..606799c5 100644 --- a/ubitx_20/ubitx.h +++ b/ubitx_20/ubitx.h @@ -24,12 +24,15 @@ //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_LCD1602I_CUST //I2C type 16 x 02 Custom Tiny Library //#define UBITX_DISPLAY_LCD2004P //24 x 04 LCD //#define UBITX_DISPLAY_LCD2004I //I2C type 24 x 04 LCD +//#define EXTEND_KEY_GROUP1 //MODE, BAND(-), BAND(+), STEP +//#define EXTEND_KEY_GROUP2 //Numeric (0~9), Point(.), Enter //Not supported in Version 1.0x + //============================================================================== // Hardware, Define PIN Usage //============================================================================== @@ -93,9 +96,17 @@ #define printLineF1(x) (printLineF(1, x)) #define printLineF2(x) (printLineF(0, x)) +#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 + extern unsigned long frequency; extern byte WsprMSGCount; extern byte sMeterLevels[9]; +extern int KeyValues[16][2]; //ADC value Ranges for Extend Key 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 b80245e4..34b99fb3 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -182,6 +182,31 @@ 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 isIFShift = 0; //1 = ifShift, 2 extend int ifShiftValue = 0; // @@ -603,7 +628,87 @@ void checkPTT(){ if (digitalRead(PTT) == 1 && inTx == 1) stopTx(); } +#ifdef EXTEND_KEY_GROUP1 +void checkButton(){ + //only if the button is pressed + int keyStatus = getBtnStatus(); + if (keyStatus == -1) + return; + + delay(50); + keyStatus = getBtnStatus(); //will be remove 3 lines + if (keyStatus == -1) + return; + + if (keyStatus == FKEY_PRESS) //Menu Key + doMenu(); + else if (keyStatus <= FKEY_STEP) //EXTEND KEY GROUP #1 + { + if (keyStatus == FKEY_MODE) //Press Mode Key + { + if (cwMode == 1) + { + cwMode = 2; + } + else if (cwMode == 2) + { + cwMode = 0; + isUSB = 0; + } + else if (isUSB == 0) + { + isUSB = 1; + } + else + { + 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 + { + char currentBandIndex = -1; + + //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 + } + else if (keyStatus == FKEY_STEP) //FKEY_BANDUP + { + if (++tuneStepIndex > 5) + tuneStepIndex = 1; + + EEPROM.put(TUNING_STEP, tuneStepIndex); + printLine2ClearAndUpdate(); + } + + FrequencyToVFO(1); + SetCarrierFreq(); + setFrequency(frequency); + //delay_background(delayTime, 0); + updateDisplay(); + } + + //wait for the button to go up again + while(keyStatus == getBtnStatus()) { + delay(10); + Check_Cat(0); + } + //delay(50);//debounce +} + +#else void checkButton(){ //only if the button is pressed if (!btnDown()) @@ -621,7 +726,7 @@ void checkButton(){ } //delay(50);//debounce } - +#endif /************************************ Replace function by KD8CEC @@ -832,6 +937,12 @@ void initSettings(){ sMeterLevels[i + 1] = EEPROM.read(S_METER_LEVELS + i); } + //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); + } + //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 56855c8b..d87a8690 100644 --- a/ubitx_20/ubitx_eemap.h +++ b/ubitx_20/ubitx_eemap.h @@ -50,9 +50,9 @@ // 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 #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 2fbfd87c..ecf363eb 100644 --- a/ubitx_20/ubitx_lcd_1602i.ino +++ b/ubitx_20/ubitx_lcd_1602i.ino @@ -44,7 +44,7 @@ //John(VK2ETA) Code #include -#define I2C_DISPLAY_ADDRESS 0x27 +#define I2C_DISPLAY_ADDRESS 0x3F //0x27 LiquidCrystal_I2C lcd(I2C_DISPLAY_ADDRESS,16,2); // set the LCD as a 16 chars and 2 line display //LiquidCrystal_I2C lcd(0x27,16,2) @@ -60,95 +60,13 @@ LiquidCrystal_I2C lcd(I2C_DISPLAY_ADDRESS,16,2); // set the LCD as a 16 chars a 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) { lcd.begin(16, 2); initMeter(); //for Meter Display + lcd.backlight(); } -//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) @@ -164,7 +82,10 @@ void printLine(unsigned char linenmbr, const char *c) { } } } - +void LCD_CreateChar(int aaa, int bbb) +{ + +} void printLineF(char linenmbr, const __FlashStringHelper *c) { int i; diff --git a/ubitx_20/ubitx_lcd_1602iian.ino b/ubitx_20/ubitx_lcd_1602iian.ino index 05123395..f5513008 100644 --- a/ubitx_20/ubitx_lcd_1602iian.ino +++ b/ubitx_20/ubitx_lcd_1602iian.ino @@ -39,7 +39,7 @@ But keep it as long as the original author of the code. Ian KD8CEC **************************************************************************/ -#define I2C_DISPLAY_ADDRESS 0x27 +#define I2C_DISPLAY_ADDRESS 0x3F //0x27 #define En B00000100 // Enable bit #define Rw B00000010 // Read/Write bit @@ -135,10 +135,22 @@ void LCD_Send(uint8_t value, uint8_t 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_Init() { //I2C Init - _Addr; + _Addr = I2C_DISPLAY_ADDRESS; _cols = 16; _rows = 2; _backlightval = LCD_NOBACKLIGHT; @@ -180,6 +192,8 @@ void LCD1602_Init() delayMicroseconds(1000); // this command takes a long time! LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT); + + backlight(); } void LCD_Print(const char *c) @@ -219,92 +233,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) { diff --git a/ubitx_20/ubitx_ui.ino b/ubitx_20/ubitx_ui.ino index e2fad8d8..faf8f53e 100644 --- a/ubitx_20/ubitx_ui.ino +++ b/ubitx_20/ubitx_ui.ino @@ -162,11 +162,36 @@ void drawMeter(int needle) //returns true if the button is pressed int btnDown(void){ +#ifdef EXTEND_KEY_GROUP1 + if (analogRead(FBUTTON) > FUNCTION_KEY_ADC) + return 0; + else + return 1; + +#else if (digitalRead(FBUTTON) == HIGH) return 0; else return 1; +#endif +} + +#ifdef EXTEND_KEY_GROUP1 +int getBtnStatus(void){ + int readButtonValue = analogRead(FBUTTON); + + if (analogRead(FBUTTON) < FUNCTION_KEY_ADC) + return FKEY_PRESS; + else + { + for (int i = 0; i < 16; i++) + if (KeyValues[i][0] <= readButtonValue && KeyValues[i][1] >= readButtonValue) + return i; + } + + return -1; } +#endif int enc_prev_state = 3; From 5611e1c0ffa258ecc89e1a7be6ec0a4de730dead Mon Sep 17 00:00:00 2001 From: phdlee Date: Wed, 18 Apr 2018 20:22:52 +0900 Subject: [PATCH 4/4] lcdtest and extended ubutton tested --- ubitx_20/ubitx.h | 19 +- ubitx_20/ubitx_20.ino | 8 +- ...ubitx_lcd_1602p.ino => ubitx_lcd_1602.ino} | 236 +++++- ubitx_20/ubitx_lcd_1602i.ino | 512 ------------- ubitx_20/ubitx_lcd_1602iian.ino | 687 ------------------ ...ubitx_lcd_2004p.ino => ubitx_lcd_2004.ino} | 218 +++++- ubitx_20/ubitx_lcd_2004i.ino | 22 - 7 files changed, 396 insertions(+), 1306 deletions(-) rename ubitx_20/{ubitx_lcd_1602p.ino => ubitx_lcd_1602.ino} (78%) delete mode 100644 ubitx_20/ubitx_lcd_1602i.ino delete mode 100644 ubitx_20/ubitx_lcd_1602iian.ino rename ubitx_20/{ubitx_lcd_2004p.ino => ubitx_lcd_2004.ino} (82%) delete mode 100644 ubitx_20/ubitx_lcd_2004i.ino diff --git a/ubitx_20/ubitx.h b/ubitx_20/ubitx.h index 606799c5..5ea76204 100644 --- a/ubitx_20/ubitx.h +++ b/ubitx_20/ubitx.h @@ -19,19 +19,22 @@ //============================================================================== // Compile Option //============================================================================== -#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. - //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_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_LCD2004I //I2C type 24 x 04 LCD +#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 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 EXTEND_KEY_GROUP1 //MODE, BAND(-), BAND(+), STEP -//#define EXTEND_KEY_GROUP2 //Numeric (0~9), Point(.), Enter //Not supported in Version 1.0x +#define SMeterLatency 3 //1 is 0.25 sec //============================================================================== // Hardware, Define PIN Usage diff --git a/ubitx_20/ubitx_20.ino b/ubitx_20/ubitx_20.ino index 34b99fb3..9ceb79ae 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -1000,10 +1000,10 @@ void initSettings(){ { //Default Setting arTuneStep[0] = 10; - arTuneStep[1] = 20; - arTuneStep[2] = 50; - arTuneStep[3] = 100; - arTuneStep[4] = 200; + arTuneStep[1] = 50; + arTuneStep[2] = 100; + arTuneStep[3] = 500; + arTuneStep[4] = 1000; } if (tuneStepIndex == 0) //New User diff --git a/ubitx_20/ubitx_lcd_1602p.ino b/ubitx_20/ubitx_lcd_1602.ino similarity index 78% rename from ubitx_20/ubitx_lcd_1602p.ino rename to ubitx_20/ubitx_lcd_1602.ino index 8b2f82ba..31623181 100644 --- a/ubitx_20/ubitx_lcd_1602p.ino +++ b/ubitx_20/ubitx_lcd_1602.ino @@ -20,34 +20,8 @@ along with this program. If not, see . **************************************************************************/ -#ifdef UBITX_DISPLAY_LCD1602P - - -//======================================================================== -//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 +//Common Defines ********************************************************* #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 @@ -85,6 +59,39 @@ uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13}; #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 +// flags for backlight control +#define LCD_BACKLIGHT 0x08 +#define LCD_NOBACKLIGHT 0x00 + +//======================================================================== +//Begin of TinyLCD Library by KD8CEC +//======================================================================== + +#ifdef UBITX_DISPLAY_LCD1602P +/************************************************************************* + 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 UBITX_DISPLAY_LCD1602_BASE + +//Define connected PIN +#define LCD_PIN_RS 8 +#define LCD_PIN_EN 9 +uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13}; + void write4bits(uint8_t value) { for (int i = 0; i < 4; i++) @@ -167,20 +174,176 @@ void LCD_CreateChar(uint8_t location, uint8_t charmap[]) for (int i=0; i<8; i++) LCD_Write(charmap[i]); } +#endif //======================================================================== //End of TinyLCD Library by KD8CEC //======================================================================== -/* -#include -LiquidCrystal lcd(8,9,10,11,12,13); -*/ -//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA -#define OPTION_SKINNYBARS //======================================================================== +//Begin of I2CTinyLCD Library by KD8CEC +//======================================================================== +#ifdef UBITX_DISPLAY_LCD1602I +#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_Init() +{ + //I2C Init + _Addr = I2C_DISPLAY_ADDRESS; + _cols = 16; + _rows = 2; + _backlightval = LCD_NOBACKLIGHT; + Wire.begin(); + + delay(50); + + // Now we pull both RS and R/W low to begin commands + 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 + + // 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(); +} + +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 I2CTinyLCD Library by KD8CEC +//======================================================================== + + +//======================================================================== +// 16 X 02 LCD Routines //Begin of Display Base Routines (Init, printLine..) //======================================================================== +#ifdef UBITX_DISPLAY_LCD1602_BASE + +//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA +#define OPTION_SKINNYBARS + char c[30], b[30]; char printBuff[2][17]; //mirrors what is showing on the two lines of the display @@ -589,9 +752,9 @@ void DisplayMeter(byte meterType, byte meterValue, char drawPosition) byte testValue = 0; char checkCount = 0; +char checkCountSMeter = 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() @@ -621,10 +784,11 @@ void idle_process() */ //S-Meter Display - if ((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) + 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); diff --git a/ubitx_20/ubitx_lcd_1602i.ino b/ubitx_20/ubitx_lcd_1602i.ino deleted file mode 100644 index ecf363eb..00000000 --- a/ubitx_20/ubitx_lcd_1602i.ino +++ /dev/null @@ -1,512 +0,0 @@ -/************************************************************************* - KD8CEC, _______ - uBITX Display Routine for LCD1602 I2C - - 1.Code for 16 x 2 LCD for I2C. - 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 . - -**************************************************************************/ -#ifdef UBITX_DISPLAY_LCD1602I - - -//======================================================================== -//Begin of LCD Hardware define -//The I2C LCD I ordered did not arrive yet. -//I referenced the I2C LCD control in the thread at the link below. -////https://groups.io/g/BITX20/topic/variation_on_ian_s_kd8cec/16657839?p=,,,20,0,0,0::recentpostdate%2Fsticky,,,20,2,0,16657839 -//In particular, I referenced the sample code of John (VK2ETA) and K9HZ. Jack, W8TEE, Nick -//======================================================================== -//#include -//LiquidCrystal lcd(8,9,10,11,12,13); - -//K9HZ's Code -//#include -//LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // - -//Jack(W8TEE) Code -//LiquidCrystal_I2C lcd(0x3F); // I2C address - -//John(VK2ETA) Code -#include -#define I2C_DISPLAY_ADDRESS 0x3F //0x27 -LiquidCrystal_I2C lcd(I2C_DISPLAY_ADDRESS,16,2); // set the LCD as a 16 chars and 2 line display - -//LiquidCrystal_I2C lcd(0x27,16,2) - - -//======================================================================== -//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 - lcd.backlight(); -} - -// 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 < 16; i++) { // add white spaces until the end of the 16 characters line is reached - lcd.write(' '); - } - } -} -void LCD_CreateChar(int aaa, int bbb) -{ - -} -void printLineF(char linenmbr, const __FlashStringHelper *c) -{ - int i; - char tmpBuff[17]; - PGM_P p = reinterpret_cast(c); - - for (i = 0; i < 17; i++){ - unsigned char fChar = pgm_read_byte(p++); - tmpBuff[i] = fChar; - if (fChar == 0) - break; - } - - printLine(linenmbr, tmpBuff); -} - -#define LCD_MAX_COLUMN 16 -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 < 16; 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 -//=================================================================================== - -// 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 - 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) - //if (inTx) - // strcat(c, " TX"); - 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[16]; -//KD8CEC 200Hz ST -//L14.150 200Hz ST -//U14.150 +150khz -int freqScrollPosition = 0; -//Example Line2 Optinal Display -//immediate execution, not call by scheulder -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] = ' '; - } - - //EXAMPLE #1 - if ((displayOption1 & 0x04) == 0x00) //none scroll display - line2Buffer[6] = 'M'; - else - { - //example #2 - if (freqScrollPosition++ > 18) //none scroll display time - { - line2Buffer[6] = 'M'; - if (freqScrollPosition > 25) - freqScrollPosition = -1; - } - else //scroll frequency - { - line2Buffer[10] = 'H'; - line2Buffer[11] = 'z'; - - if (freqScrollPosition < 7) - { - for (int i = 11; i >= 0; i--) - if (i - (7 - freqScrollPosition) >= 0) - line2Buffer[i] = line2Buffer[i - (7 - freqScrollPosition)]; - else - line2Buffer[i] = ' '; - } - else - { - for (int i = 0; i < 11; i++) - if (i + (freqScrollPosition - 7) <= 11) - line2Buffer[i] = line2Buffer[i + (freqScrollPosition - 7)]; - else - line2Buffer[i] = ' '; - } - } - } //scroll - - line2Buffer[7] = ' '; - - if (isIFShift) - { -// if (isDirectCall == 1) -// for (int i = 0; i < 16; i++) -// line2Buffer[i] = ' '; - - //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); - - //if (isDirectCall == 1) //if call by encoder (not scheduler), immediate print value - printLine2(line2Buffer); - } // end of display IF - else // step & Key Type display - { - //if (isDirectCall != 0) - // return; - - memset(&line2Buffer[8], ' ', 8); - //Step - long tmpStep = arTuneStep[tuneStepIndex -1]; - - byte isStepKhz = 0; - if (tmpStep >= 1000) - { - isStepKhz = 2; - } - - for (int i = 10; i >= 8 - isStepKhz; i--) { - if (tmpStep > 0) { - line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30; - tmpStep /= 10; - } - else - line2Buffer[i +isStepKhz] = ' '; - } - - if (isStepKhz == 0) - { - line2Buffer[11] = 'H'; - line2Buffer[12] = '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'; - } - } -} - -//meterType : 0 = S.Meter, 1 : P.Meter -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; - - lcd.setCursor(drawPosition, lineNumber); - - for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6 - lcd.write(lcdMeter[i]); - } -} - -byte testValue = 0; -char checkCount = 0; -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; - } - - //EX for Meters - /* - DisplayMeter(0, testValue++, 7); - if (testValue > 30) - testValue = 0; - */ - } - } -} - -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) -{ - printLineFromEEPRom(0, 0, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) - //delay(500); -} - -void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) -{ - printLineF(1, fwVersionInfo); -} - - -#endif diff --git a/ubitx_20/ubitx_lcd_1602iian.ino b/ubitx_20/ubitx_lcd_1602iian.ino deleted file mode 100644 index f5513008..00000000 --- a/ubitx_20/ubitx_lcd_1602iian.ino +++ /dev/null @@ -1,687 +0,0 @@ -/************************************************************************* - KD8CEC's uBITX Display Routine for LCD1602 Parrel - 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 . - -**************************************************************************/ -#ifdef UBITX_DISPLAY_LCD1602I_CUST -#include - -//======================================================================== -//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. - Ian KD8CEC -**************************************************************************/ -#define I2C_DISPLAY_ADDRESS 0x3F //0x27 - -#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)) - -//Define connected PIN -//#define LCD_PIN_RS 8 -//#define LCD_PIN_EN 9 -//uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13}; - -uint8_t _Addr; -uint8_t _displayfunction; -uint8_t _displaycontrol; -uint8_t _displaymode; -uint8_t _numlines; -uint8_t _cols; -uint8_t _rows; -uint8_t _backlightval; - -// 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 - -// flags for backlight control -#define LCD_BACKLIGHT 0x08 -#define LCD_NOBACKLIGHT 0x00 - -#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_Init() -{ - //I2C Init - _Addr = I2C_DISPLAY_ADDRESS; - _cols = 16; - _rows = 2; - _backlightval = LCD_NOBACKLIGHT; - Wire.begin(); - - delay(50); - - // Now we pull both RS and R/W low to begin commands - 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 - - // 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(); -} - -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]); -} -//======================================================================== -//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) -{ - LCD1602_Init(); - initMeter(); //for Meter Display -} - - -// 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 < 16; i++) { // add white spaces until the end of the 16 characters line is reached - LCD_Write(' '); - } - } -} - -void printLineF(char linenmbr, const __FlashStringHelper *c) -{ - int i; - char tmpBuff[17]; - PGM_P p = reinterpret_cast(c); - - for (i = 0; i < 17; i++){ - unsigned char fChar = pgm_read_byte(p++); - tmpBuff[i] = fChar; - if (fChar == 0) - break; - } - - printLine(linenmbr, tmpBuff); -} - -#define LCD_MAX_COLUMN 16 -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 < 16; 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 - 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) - //if (inTx) - // strcat(c, " TX"); - 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[16]; -//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] = ' '; - } - - //EXAMPLE #1 - if ((displayOption1 & 0x04) == 0x00) //none scroll display - line2Buffer[6] = 'M'; - else - { - //example #2 - if (freqScrollPosition++ > 18) //none scroll display time - { - line2Buffer[6] = 'M'; - if (freqScrollPosition > 25) - freqScrollPosition = -1; - } - else //scroll frequency - { - line2Buffer[10] = 'H'; - line2Buffer[11] = 'z'; - - if (freqScrollPosition < 7) - { - for (int i = 11; i >= 0; i--) - if (i - (7 - freqScrollPosition) >= 0) - line2Buffer[i] = line2Buffer[i - (7 - freqScrollPosition)]; - else - line2Buffer[i] = ' '; - } - else - { - for (int i = 0; i < 11; i++) - if (i + (freqScrollPosition - 7) <= 11) - line2Buffer[i] = line2Buffer[i + (freqScrollPosition - 7)]; - else - line2Buffer[i] = ' '; - } - } - } //scroll - - line2Buffer[7] = ' '; - - if (isIFShift) - { -// if (isDirectCall == 1) -// for (int i = 0; i < 16; i++) -// line2Buffer[i] = ' '; - - //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); - - //if (isDirectCall == 1) //if call by encoder (not scheduler), immediate print value - printLine2(line2Buffer); - } // end of display IF - else // step & Key Type display - { - //if (isDirectCall != 0) - // return; - - memset(&line2Buffer[8], ' ', 8); - //Step - long tmpStep = arTuneStep[tuneStepIndex -1]; - - byte isStepKhz = 0; - if (tmpStep >= 1000) - { - isStepKhz = 2; - } - - for (int i = 10; i >= 8 - isStepKhz; i--) { - if (tmpStep > 0) { - line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30; - tmpStep /= 10; - } - else - line2Buffer[i +isStepKhz] = ' '; - } - - if (isStepKhz == 0) - { - line2Buffer[11] = 'H'; - line2Buffer[12] = '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'; - } - } -} - -//meterType : 0 = S.Meter, 1 : P.Meter -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; - - LCD_SetCursor(drawPosition, lineNumber); - - for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6 - LCD_Write(lcdMeter[i]); - } -} - -byte testValue = 0; -char checkCount = 0; -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; - } - - //EX for Meters - /* - DisplayMeter(0, testValue++, 7); - if (testValue > 30) - testValue = 0; - */ - } - } -} - -//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) -{ - printLineFromEEPRom(0, 0, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) - //delay(500); -} - -void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) -{ - printLineF(1, fwVersionInfo); -} - - -#endif diff --git a/ubitx_20/ubitx_lcd_2004p.ino b/ubitx_20/ubitx_lcd_2004.ino similarity index 82% rename from ubitx_20/ubitx_lcd_2004p.ino rename to ubitx_20/ubitx_lcd_2004.ino index fb29ec00..8e552a63 100644 --- a/ubitx_20/ubitx_lcd_2004p.ino +++ b/ubitx_20/ubitx_lcd_2004.ino @@ -20,33 +20,8 @@ along with this program. If not, see . **************************************************************************/ -#ifdef UBITX_DISPLAY_LCD2004P - -//======================================================================== -//Begin of TinyLCD Library by KD8CEC -//======================================================================== -/************************************************************************* - LCD2004TINY Library for 20 x 4 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 +//Common Defines ********************************************************* #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 @@ -84,6 +59,38 @@ uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13}; #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 +// flags for backlight control +#define LCD_BACKLIGHT 0x08 +#define LCD_NOBACKLIGHT 0x00 + +//======================================================================== +//Begin of TinyLCD Library by KD8CEC +//======================================================================== + +#ifdef UBITX_DISPLAY_LCD2004P +/************************************************************************* + LCD2004TINY Library for 20 x 4 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 UBITX_DISPLAY_LCD2004_BASE + +//Define connected PIN +#define LCD_PIN_RS 8 +#define LCD_PIN_EN 9 +uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13}; + void write4bits(uint8_t value) { for (int i = 0; i < 4; i++) @@ -144,6 +151,152 @@ void LCD2004_Init() LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT); } +#endif +//======================================================================== +//End of TinyLCD Library by KD8CEC +//======================================================================== + + + +//======================================================================== +//Begin of I2CTinyLCD Library by KD8CEC +//======================================================================== +#ifdef UBITX_DISPLAY_LCD2004I + +#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_LCD2004_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 LCD2004_Init() +{ + //I2C Init + _Addr = I2C_DISPLAY_ADDRESS; + _cols = 20; + _rows = 4; + _backlightval = LCD_NOBACKLIGHT; + Wire.begin(); + + delay(50); + + // Now we pull both RS and R/W low to begin commands + 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 + + // 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(); +} +#endif +//======================================================================== +//End of I2CTinyLCD Library by KD8CEC +//======================================================================== + + +//======================================================================== +// 20 X 04 LCD Routines +//Begin of Display Base Routines (Init, printLine..) +//======================================================================== +#ifdef UBITX_DISPLAY_LCD2004_BASE void LCD_Print(const char *c) { @@ -167,20 +320,10 @@ void LCD_CreateChar(uint8_t location, uint8_t charmap[]) 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); -*/ //SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA //#define OPTION_SKINNYBARS -//======================================================================== -//Begin of Display Base Routines (Init, printLine..) -//======================================================================== char c[30], b[30]; char printBuff[4][20]; //mirrors what is showing on the two lines of the display @@ -623,6 +766,7 @@ char checkCount = 0; int currentSMeter = 0; //int sMeterLevels[] = {0, 5, 17, 41, 74, 140, 255, 365, 470}; byte scaledSMeter = 0; +char checkCountSMeter = 0; //execute interval : 0.25sec void idle_process() @@ -660,7 +804,7 @@ void idle_process() // testValue = 0; //S-Meter Display - if ((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) + if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency)) { int newSMeter; diff --git a/ubitx_20/ubitx_lcd_2004i.ino b/ubitx_20/ubitx_lcd_2004i.ino deleted file mode 100644 index bee57aba..00000000 --- a/ubitx_20/ubitx_lcd_2004i.ino +++ /dev/null @@ -1,22 +0,0 @@ -/************************************************************************* - KD8CEC's uBITX Display Routine for LCD2404 I2C - 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 . - -**************************************************************************/ - -