commit
0996870154
@ -611,6 +611,34 @@ void WriteEEPRom_FT817(byte fromType)
|
||||
Serial.write(ACK);
|
||||
}
|
||||
|
||||
const byte anlogPinIndex[6] = {A0, A1, A2, A3, A6, A7};
|
||||
|
||||
//Read ADC Value by uBITX Manager Software
|
||||
void ReadADCValue(void)
|
||||
{
|
||||
//ADC MAP for uBITX
|
||||
int readedADCValue;
|
||||
//5BYTES
|
||||
//CAT_BUFF[0] [1] [2] [3] [4] //4 COMMAND
|
||||
//0 READ ADDRESS
|
||||
readedADCValue = analogRead(anlogPinIndex[CAT_BUFF[0]]);
|
||||
CAT_BUFF[0] = readedADCValue >> 8;
|
||||
CAT_BUFF[1] = readedADCValue;
|
||||
SendCatData(2);
|
||||
Serial.write(ACK);
|
||||
}
|
||||
|
||||
void SetIFSValue(void)
|
||||
{
|
||||
//Set IFShift Value
|
||||
isIFShift = CAT_BUFF[0];
|
||||
ifShiftValue = CAT_BUFF[1] + CAT_BUFF[2] * 256;
|
||||
setFrequency(frequency);
|
||||
SetCarrierFreq();
|
||||
updateLine2Buffer(1); //option, perhap not need
|
||||
Serial.write(ACK);
|
||||
}
|
||||
|
||||
//void CatRxStatus(byte fromType)
|
||||
void CatRxStatus(void) //for remove warning
|
||||
{
|
||||
@ -768,6 +796,14 @@ void Check_Cat(byte fromType)
|
||||
WriteEEPRom_FT817(fromType);
|
||||
break;
|
||||
|
||||
case 0xDD: //Read uBITX ADC Data
|
||||
ReadADCValue(); //Call by uBITX Manager Program
|
||||
break;
|
||||
|
||||
case 0xDE: //IF-Shift Control by CAT
|
||||
SetIFSValue(); //
|
||||
break;
|
||||
|
||||
case 0xE7 : //Read RX Status
|
||||
CatRxStatus();
|
||||
break;
|
||||
|
@ -299,13 +299,14 @@ void controlAutoCW(){
|
||||
|
||||
printLineFromEEPRom(0, 2, cwStartIndex + displayScrolStep + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ, 0);
|
||||
|
||||
byte diplayAutoCWLine = 0;
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayAutoCWLine = 1;
|
||||
|
||||
lcd.setCursor(0, diplayAutoCWLine);
|
||||
lcd.write(byteToChar(selectedCWTextIndex));
|
||||
lcd.write(':');
|
||||
//byte diplayAutoCWLine = 0;
|
||||
//if ((displayOption1 & 0x01) == 0x01)
|
||||
// diplayAutoCWLine = 1;
|
||||
|
||||
Display_AutoKeyTextIndex(selectedCWTextIndex);
|
||||
//lcd.setCursor(0, diplayAutoCWLine);
|
||||
//lcd.write(byteToChar(selectedCWTextIndex));
|
||||
//lcd.write(':');
|
||||
isNeedScroll = (cwEndIndex - cwStartIndex) > 14 ? 1 : 0;
|
||||
scrollDispayTime = millis() + scrollSpeed;
|
||||
beforeCWTextIndex = selectedCWTextIndex;
|
||||
|
@ -34,6 +34,7 @@ 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;
|
||||
|
||||
|
@ -1,8 +1,25 @@
|
||||
//Firmware Version
|
||||
#define FIRMWARE_VERSION_INFO F("CE v1.070")
|
||||
#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.
|
||||
|
||||
|
||||
/**
|
||||
Since KD8CEC Version 0.29, most of the original code is no longer available.
|
||||
Cat Suppoort uBITX CEC Version
|
||||
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.
|
||||
DE Ian KD8CEC
|
||||
Ian KD8CEC
|
||||
|
||||
Original source comment -------------------------------------------------------------
|
||||
* This source file is under General Public License version 3.
|
||||
@ -87,25 +104,6 @@
|
||||
#define ANALOG_SPARE (A7)
|
||||
#define ANALOG_SMETER (A7) //by KD8CEC
|
||||
|
||||
/**
|
||||
* The Raduino board is the size of a standard 16x2 LCD panel. It has three connectors:
|
||||
*
|
||||
* First, is an 8 pin connector that provides +5v, GND and six analog input pins that can also be
|
||||
* configured to be used as digital input or output pins. These are referred to as A0,A1,A2,
|
||||
* A3,A6 and A7 pins. The A4 and A5 pins are missing from this connector as they are used to
|
||||
* talk to the Si5351 over I2C protocol.
|
||||
*
|
||||
* Second is a 16 pin LCD connector. This connector is meant specifically for the standard 16x2
|
||||
* LCD display in 4 bit mode. The 4 bit mode requires 4 data lines and two control lines to work:
|
||||
* Lines used are : RESET, ENABLE, D4, D5, D6, D7
|
||||
* We include the library and declare the configuration of the LCD panel too
|
||||
*/
|
||||
|
||||
#include <LiquidCrystal.h>
|
||||
LiquidCrystal lcd(8,9,10,11,12,13);
|
||||
|
||||
#define VERSION_NUM 0x01 //for KD8CEC'S firmware and for memory management software
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -117,8 +115,6 @@ LiquidCrystal lcd(8,9,10,11,12,13);
|
||||
* 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.
|
||||
*/
|
||||
char c[30], b[30];
|
||||
char printBuff[2][17]; //mirrors what is showing on the two lines of the display
|
||||
int count = 0; //to generally count ticks, loops, etc
|
||||
|
||||
/**
|
||||
@ -151,7 +147,12 @@ int count = 0; //to generally count ticks, loops, etc
|
||||
#define CW_SIDETONE 24
|
||||
#define CW_SPEED 28
|
||||
|
||||
//AT328 has 1KBytes EEPROM
|
||||
//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
|
||||
@ -332,6 +333,12 @@ unsigned long dbgCount = 0; //not used now
|
||||
unsigned char txFilter = 0; //which of the four transmit filters are in use
|
||||
boolean modeCalibrate = false;//this mode of menus shows extended menus to calibrate the oscillators and choose the proper
|
||||
//beat frequency
|
||||
|
||||
byte advancedFreqOption1; //255 : Bit0: use IFTune_Value, Bit1 : use Stored enabled SDR Mode, Bit2 : dynamic sdr frequency
|
||||
byte attLevel = 0; //ATT : RF Gain Control (Receive) <-- IF1 Shift, 0 : Off, ShiftValue is attLevel * 100; attLevel 150 = 15K
|
||||
char 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 beforeIdle_ProcessTime = 0; //for check Idle time
|
||||
byte line2DisplayStatus = 0; //0:Clear, 1 : menu, 1: DisplayFrom Idle,
|
||||
@ -502,7 +509,50 @@ void setFrequency(unsigned long f){
|
||||
setTXFilters(f);
|
||||
|
||||
unsigned long appliedCarrier = ((cwMode == 0 ? usbCarrier : cwmCarrier) + (isIFShift && (inTx == 0) ? ifShiftValue : 0));
|
||||
long if1AdjustValue = ((inTx == 0) ? (attLevel * 100) : 0) + (if1TuneValue * 100); //if1Tune RX, TX Enabled, ATT : only RX Mode
|
||||
|
||||
if (sdrModeOn && (inTx == 0)) //IF SDR
|
||||
{
|
||||
//Fixed Frequency SDR (Default Frequency : 32Mhz, available change sdr Frequency by uBITX Manager)
|
||||
//Dynamic Frequency is for SWL without cat
|
||||
//Offset Frequency + Mhz,
|
||||
//Example : Offset Frequency : 30Mhz and current Frequncy is 7.080 => 37.080Mhz
|
||||
// Offset Frequency : 30Mhz and current Frequncy is 14.074 => 34.074Mhz
|
||||
|
||||
//Dynamic Frequency
|
||||
//if (advancedFreqOption1 & 0x04 != 0x00)
|
||||
// if1AdjustValue += (f % 10000000);
|
||||
|
||||
si5351bx_setfreq(2, 44991500 + if1AdjustValue + f);
|
||||
si5351bx_setfreq(1, 44991500
|
||||
+ if1AdjustValue
|
||||
+ SDR_Center_Freq
|
||||
+ ((advancedFreqOption1 & 0x04) == 0x00 ? 0 : (f % 10000000))
|
||||
+ 2390);
|
||||
/*
|
||||
si5351bx_setfreq(2, 44999500 + f);
|
||||
si5351bx_setfreq(1, 44999500 + SDR_Center_Freq + 2390);
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cwMode == 1 || (cwMode == 0 && (!isUSB)))
|
||||
{
|
||||
//CWL(cwMode == 1) or LSB (cwMode == 0 && (!isUSB))
|
||||
si5351bx_setfreq(2, SECOND_OSC_LSB + if1AdjustValue + appliedCarrier + f);
|
||||
//si5351bx_setfreq(1, SECOND_OSC_LSB + if1AdjustValue - (sdrModeOn ? (SDR_Center_Freq- usbCarrier) : 0));
|
||||
si5351bx_setfreq(1, SECOND_OSC_LSB + if1AdjustValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
//CWU (cwMode == 2) or LSB (cwMode == 0 and isUSB)
|
||||
si5351bx_setfreq(2, SECOND_OSC_USB + if1AdjustValue - appliedCarrier + f);
|
||||
//si5351bx_setfreq(1, SECOND_OSC_USB + if1AdjustValue + (sdrModeOn ? (SDR_Center_Freq- usbCarrier) : 0)); //Increase LO Frequency => 1198500 -> 32Mhz
|
||||
si5351bx_setfreq(1, SECOND_OSC_USB + if1AdjustValue); //Increase LO Frequency => 1198500 -> 32Mhz
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (cwMode == 0)
|
||||
{
|
||||
if (isUSB){
|
||||
@ -525,6 +575,7 @@ void setFrequency(unsigned long f){
|
||||
si5351bx_setfreq(1, SECOND_OSC_USB);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
frequency = f;
|
||||
}
|
||||
@ -606,13 +657,6 @@ void stopTx(void){
|
||||
inTx = 0;
|
||||
|
||||
digitalWrite(TX_RX, 0); //turn off the tx
|
||||
|
||||
/*
|
||||
if (cwMode == 0)
|
||||
si5351bx_setfreq(0, usbCarrier + (isIFShift ? ifShiftValue : 0)); //set back the carrier oscillator anyway, cw tx switches it off
|
||||
else
|
||||
si5351bx_setfreq(0, cwmCarrier + (isIFShift ? ifShiftValue : 0)); //set back the carrier oscillator anyway, cw tx switches it off
|
||||
*/
|
||||
SetCarrierFreq();
|
||||
|
||||
if (ritOn)
|
||||
@ -669,7 +713,7 @@ void ritDisable(){
|
||||
* flip the T/R line to T and update the display to denote transmission
|
||||
*/
|
||||
|
||||
void checkPTT(){
|
||||
void checkPTT(){
|
||||
//we don't check for ptt when transmitting cw
|
||||
if (cwTimeout > 0)
|
||||
return;
|
||||
@ -678,7 +722,7 @@ void checkPTT(){
|
||||
startTx(TX_SSB, 1);
|
||||
delay(50); //debounce the PTT
|
||||
}
|
||||
|
||||
|
||||
if (digitalRead(PTT) == 1 && inTx == 1)
|
||||
stopTx();
|
||||
}
|
||||
@ -862,7 +906,7 @@ void initSettings(){
|
||||
|
||||
printLineF(1, F("Init EEProm..."));
|
||||
//initial all eeprom
|
||||
for (unsigned int i = 32; i < 1024; i++) //protect Master_cal, usb_cal
|
||||
for (unsigned int i = 64; i < 1024; i++) //protect Master_cal, usb_cal
|
||||
EEPROM.write(i, 0);
|
||||
|
||||
//Write Firmware ID
|
||||
@ -872,8 +916,8 @@ void initSettings(){
|
||||
}
|
||||
|
||||
//Version Write for Memory Management Software
|
||||
if (EEPROM.read(VERSION_ADDRESS) != VERSION_NUM)
|
||||
EEPROM.write(VERSION_ADDRESS, VERSION_NUM);
|
||||
if (EEPROM.read(VERSION_ADDRESS) != FIRMWARE_VERSION_NUM)
|
||||
EEPROM.write(VERSION_ADDRESS, FIRMWARE_VERSION_NUM);
|
||||
|
||||
EEPROM.get(CW_CAL, cwmCarrier);
|
||||
|
||||
@ -1015,6 +1059,25 @@ void initSettings(){
|
||||
isIFShift = ifShiftValue != 0;
|
||||
}
|
||||
|
||||
//Advanced Freq control
|
||||
EEPROM.get(ADVANCED_FREQ_OPTION1, advancedFreqOption1);
|
||||
|
||||
//use Advanced Frequency Control
|
||||
if (advancedFreqOption1 & 0x01 != 0x00)
|
||||
{
|
||||
EEPROM.get(IF1_CAL, if1TuneValue);
|
||||
|
||||
//Stored Enabled SDR Mode
|
||||
if (advancedFreqOption1 & 0x02 != 0x00)
|
||||
{
|
||||
EEPROM.get(ENABLE_SDR, sdrModeOn);
|
||||
}
|
||||
}
|
||||
|
||||
EEPROM.get(SDR_FREQUNCY, SDR_Center_Freq);
|
||||
if (SDR_Center_Freq == 0)
|
||||
SDR_Center_Freq = 32000000;
|
||||
|
||||
//default Value (for original hardware)
|
||||
if (cwAdcSTFrom >= cwAdcSTTo)
|
||||
{
|
||||
@ -1137,11 +1200,10 @@ void setup()
|
||||
*/
|
||||
|
||||
//Serial.begin(9600);
|
||||
lcd.begin(16, 2);
|
||||
printLineF(1, F("CE v1.061"));
|
||||
LCD_Init();
|
||||
printLineF(1, FIRMWARE_VERSION_INFO);
|
||||
|
||||
Init_Cat(38400, SERIAL_8N1);
|
||||
initMeter(); //not used in this build
|
||||
initSettings();
|
||||
|
||||
if (userCallsignLength > 0 && ((userCallsignLength & 0x80) == 0x80)) {
|
||||
@ -1165,8 +1227,10 @@ void setup()
|
||||
setFrequency(vfoA);
|
||||
updateDisplay();
|
||||
|
||||
#ifdef ENABLE_FACTORYALIGN
|
||||
if (btnDown())
|
||||
factory_alignment();
|
||||
#endif
|
||||
}
|
||||
|
||||
//Auto save Frequency and Mode with Protected eeprom life by KD8CEC
|
||||
|
@ -1,254 +0,0 @@
|
||||
/*************************************************************************
|
||||
KD8CEC's 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
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 isDirectCall)
|
||||
{
|
||||
unsigned long tmpFreq = 0;
|
||||
if (isDirectCall == 0)
|
||||
{
|
||||
if (ritOn)
|
||||
{
|
||||
strcpy(line2Buffer, "RitTX:");
|
||||
|
||||
//display frequency
|
||||
tmpFreq = ritTxFrequency;
|
||||
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] = ' ';
|
||||
} //check direct call by encoder
|
||||
|
||||
if (isIFShift)
|
||||
{
|
||||
if (isDirectCall == 1)
|
||||
for (int i = 0; i < 16; i++)
|
||||
line2Buffer[i] = ' ';
|
||||
|
||||
//IFShift Offset Value
|
||||
line2Buffer[8] = 'I';
|
||||
line2Buffer[9] = 'F';
|
||||
|
||||
//if (ifShiftValue == 0)
|
||||
//{
|
||||
/*
|
||||
line2Buffer[10] = 'S';
|
||||
line2Buffer[11] = ':';
|
||||
line2Buffer[12] = 'O';
|
||||
line2Buffer[13] = 'F';
|
||||
line2Buffer[14] = 'F';
|
||||
*/
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
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 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 == 1)
|
||||
// line2Buffer[10] = 'k';
|
||||
|
||||
if (isStepKhz == 0)
|
||||
{
|
||||
line2Buffer[11] = 'H';
|
||||
line2Buffer[12] = 'z';
|
||||
}
|
||||
|
||||
line2Buffer[13] = ' ';
|
||||
//if (
|
||||
//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;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
552
ubitx_20/ubitx_lcd_1602i.ino
Normal file
552
ubitx_20/ubitx_lcd_1602i.ino
Normal file
@ -0,0 +1,552 @@
|
||||
/*************************************************************************
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
#ifdef UBITX_DISPLAY_LCD1602I
|
||||
|
||||
|
||||
//========================================================================
|
||||
//Begin of LCD Hardware define
|
||||
//========================================================================
|
||||
#include <LiquidCrystal.h>
|
||||
LiquidCrystal lcd(8,9,10,11,12,13);
|
||||
|
||||
|
||||
//========================================================================
|
||||
//End of LCD Hardware define
|
||||
//========================================================================
|
||||
|
||||
//========================================================================
|
||||
//Begin of Display Base Routines (Init, printLine..)
|
||||
//========================================================================
|
||||
char c[30], b[30];
|
||||
char printBuff[2][17]; //mirrors what is showing on the two lines of the display
|
||||
|
||||
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<PGM_P>(meters_bitmap);
|
||||
|
||||
const PROGMEM uint8_t lock_bitmap[8] = {
|
||||
0b01110,
|
||||
0b10001,
|
||||
0b10001,
|
||||
0b11111,
|
||||
0b11011,
|
||||
0b11011,
|
||||
0b11111,
|
||||
0b00000};
|
||||
PGM_P plock_bitmap = reinterpret_cast<PGM_P>(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
|
||||
}
|
||||
|
||||
//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<PGM_P>(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;
|
||||
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;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Display_AutoKeyTextIndex(char textIndex)
|
||||
{
|
||||
byte diplayAutoCWLine = 0;
|
||||
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayAutoCWLine = 1;
|
||||
lcd.setCursor(0, diplayAutoCWLine);
|
||||
lcd.write(byteToChar(selectedCWTextIndex));
|
||||
lcd.write(':');
|
||||
}
|
||||
|
||||
|
||||
#endif
|
694
ubitx_20/ubitx_lcd_1602p.ino
Normal file
694
ubitx_20/ubitx_lcd_1602p.ino
Normal file
@ -0,0 +1,694 @@
|
||||
/*************************************************************************
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
#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
|
||||
#define LCD_CLEARDISPLAY 0x01
|
||||
#define LCD_RETURNHOME 0x02
|
||||
#define LCD_ENTRYMODESET 0x04
|
||||
#define LCD_DISPLAYCONTROL 0x08
|
||||
#define LCD_CURSORSHIFT 0x10
|
||||
#define LCD_FUNCTIONSET 0x20
|
||||
#define LCD_SETCGRAMADDR 0x40
|
||||
#define LCD_SETDDRAMADDR 0x80
|
||||
|
||||
// flags for display entry mode
|
||||
#define LCD_ENTRYRIGHT 0x00
|
||||
#define LCD_ENTRYLEFT 0x02
|
||||
#define LCD_ENTRYSHIFTINCREMENT 0x01
|
||||
#define LCD_ENTRYSHIFTDECREMENT 0x00
|
||||
|
||||
// flags for display on/off control
|
||||
#define LCD_DISPLAYON 0x04
|
||||
#define LCD_DISPLAYOFF 0x00
|
||||
#define LCD_CURSORON 0x02
|
||||
#define LCD_CURSOROFF 0x00
|
||||
#define LCD_BLINKON 0x01
|
||||
#define LCD_BLINKOFF 0x00
|
||||
|
||||
// flags for display/cursor shift
|
||||
#define LCD_DISPLAYMOVE 0x08
|
||||
#define LCD_CURSORMOVE 0x00
|
||||
#define LCD_MOVERIGHT 0x04
|
||||
#define LCD_MOVELEFT 0x00
|
||||
|
||||
// flags for function set
|
||||
#define LCD_8BITMODE 0x10
|
||||
#define LCD_4BITMODE 0x00
|
||||
#define LCD_2LINE 0x08
|
||||
#define LCD_1LINE 0x00
|
||||
#define LCD_5x10DOTS 0x04
|
||||
#define LCD_5x8DOTS 0x00
|
||||
|
||||
void write4bits(uint8_t value)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
digitalWrite(LCD_PIN_DAT[i], (value >> i) & 0x01);
|
||||
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(LCD_PIN_EN, HIGH);
|
||||
delayMicroseconds(1); // enable pulse must be >450ns
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
delayMicroseconds(100); // commands need > 37us to settle
|
||||
}
|
||||
|
||||
void LCD_Send(uint8_t value, uint8_t mode)
|
||||
{
|
||||
digitalWrite(LCD_PIN_RS, mode);
|
||||
write4bits(value>>4);
|
||||
write4bits(value);
|
||||
}
|
||||
|
||||
void LCD1602_Init()
|
||||
{
|
||||
pinMode(LCD_PIN_RS, OUTPUT);
|
||||
pinMode(LCD_PIN_EN, OUTPUT);
|
||||
for (int i = 0; i < 4; i++)
|
||||
pinMode(LCD_PIN_DAT[i], OUTPUT);
|
||||
|
||||
delayMicroseconds(50);
|
||||
|
||||
// Now we pull both RS and R/W low to begin commands
|
||||
digitalWrite(LCD_PIN_RS, LOW);
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
|
||||
// we start in 8bit mode, try to set 4 bit mode
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// second try
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// third go!
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(150);
|
||||
|
||||
// finally, set to 4-bit interface
|
||||
write4bits(0x02);
|
||||
|
||||
// finally, set # lines, font size, etc.
|
||||
LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE);
|
||||
|
||||
// turn the display on with no cursor or blinking default
|
||||
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
|
||||
|
||||
// clear it off
|
||||
LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||
delayMicroseconds(2000); // this command takes a long time!
|
||||
|
||||
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
|
||||
}
|
||||
|
||||
void LCD_Print(const char *c)
|
||||
{
|
||||
for (int i = 0; i < strlen(c); i++)
|
||||
{
|
||||
if (*(c + i) == 0x00) return;
|
||||
LCD_Write(*(c + i));
|
||||
}
|
||||
}
|
||||
|
||||
void LCD_SetCursor(uint8_t col, uint8_t row)
|
||||
{
|
||||
LCD_Command(LCD_SETDDRAMADDR | (col + row * 0x40)); //0 : 0x00, 1 : 0x40, only for 16 x 2 lcd
|
||||
}
|
||||
|
||||
void LCD_CreateChar(uint8_t location, uint8_t charmap[])
|
||||
{
|
||||
location &= 0x7; // we only have 8 locations 0-7
|
||||
LCD_Command(LCD_SETCGRAMADDR | (location << 3));
|
||||
for (int i=0; i<8; i++)
|
||||
LCD_Write(charmap[i]);
|
||||
}
|
||||
//========================================================================
|
||||
//End of TinyLCD Library by KD8CEC
|
||||
//========================================================================
|
||||
|
||||
/*
|
||||
#include <LiquidCrystal.h>
|
||||
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<PGM_P>(meters_bitmap);
|
||||
|
||||
const PROGMEM uint8_t lock_bitmap[8] = {
|
||||
0b01110,
|
||||
0b10001,
|
||||
0b10001,
|
||||
0b11111,
|
||||
0b11011,
|
||||
0b11011,
|
||||
0b11111,
|
||||
0b00000};
|
||||
PGM_P plock_bitmap = reinterpret_cast<PGM_P>(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<PGM_P>(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
|
||||
void updateLine2Buffer(char displayType)
|
||||
{
|
||||
unsigned long tmpFreq = 0;
|
||||
if (ritOn)
|
||||
{
|
||||
strcpy(line2Buffer, "RitTX:");
|
||||
|
||||
//display frequency
|
||||
tmpFreq = ritTxFrequency;
|
||||
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(char textIndex)
|
||||
{
|
||||
byte diplayAutoCWLine = 0;
|
||||
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayAutoCWLine = 1;
|
||||
LCD_SetCursor(0, diplayAutoCWLine);
|
||||
LCD_Write(byteToChar(selectedCWTextIndex));
|
||||
LCD_Write(':');
|
||||
}
|
||||
|
||||
|
||||
#endif
|
22
ubitx_20/ubitx_lcd_2404i.ino
Normal file
22
ubitx_20/ubitx_lcd_2404i.ino
Normal file
@ -0,0 +1,22 @@
|
||||
/*************************************************************************
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
22
ubitx_20/ubitx_lcd_2404p.ino
Normal file
22
ubitx_20/ubitx_lcd_2404p.ino
Normal file
@ -0,0 +1,22 @@
|
||||
/*************************************************************************
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -127,7 +127,7 @@ void si5351_set_calibration(int32_t cal){
|
||||
void SetCarrierFreq()
|
||||
{
|
||||
unsigned long appliedCarrier = ((cwMode == 0 ? usbCarrier : cwmCarrier) + (isIFShift && (inTx == 0) ? ifShiftValue : 0));
|
||||
si5351bx_setfreq(0, appliedCarrier);
|
||||
si5351bx_setfreq(0, (sdrModeOn ? 0 : appliedCarrier));
|
||||
|
||||
/*
|
||||
if (cwMode == 0)
|
||||
|
@ -5,8 +5,13 @@
|
||||
* of the radio. Occasionally, it is used to provide a two-line information that is
|
||||
* quickly cleared up.
|
||||
*/
|
||||
//#define printLineF1(x) (printLineF(1, x))
|
||||
//#define printLineF2(x) (printLineF(0, x))
|
||||
|
||||
char byteToChar(byte srcByte){
|
||||
if (srcByte < 10)
|
||||
return 0x30 + srcByte;
|
||||
else
|
||||
return 'A' + srcByte - 10;
|
||||
}
|
||||
|
||||
//returns true if the button is pressed
|
||||
int btnDown(void){
|
||||
@ -16,319 +21,6 @@ int btnDown(void){
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Meter (not used in this build for anything)
|
||||
* the meter is drawn using special characters. Each character is composed of 5 x 8 matrix.
|
||||
* The s_meter array holds the definition of the these characters.
|
||||
* each line of the array is is one character such that 5 bits of every byte
|
||||
* makes up one line of pixels of the that character (only 5 bits are used)
|
||||
* The current reading of the meter is assembled in the string called meter
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
const PROGMEM uint8_t s_meter_bitmap[] = {
|
||||
B00000,B00000,B00000,B00000,B00000,B00100,B00100,B11011,
|
||||
B10000,B10000,B10000,B10000,B10100,B10100,B10100,B11011,
|
||||
B01000,B01000,B01000,B01000,B01100,B01100,B01100,B11011,
|
||||
B00100,B00100,B00100,B00100,B00100,B00100,B00100,B11011,
|
||||
B00010,B00010,B00010,B00010,B00110,B00110,B00110,B11011,
|
||||
B00001,B00001,B00001,B00001,B00101,B00101,B00101,B11011
|
||||
};
|
||||
*/
|
||||
|
||||
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<PGM_P>(meters_bitmap);
|
||||
|
||||
const PROGMEM uint8_t lock_bitmap[8] = {
|
||||
0b01110,
|
||||
0b10001,
|
||||
0b10001,
|
||||
0b11111,
|
||||
0b11011,
|
||||
0b11011,
|
||||
0b11111,
|
||||
0b00000};
|
||||
PGM_P plock_bitmap = reinterpret_cast<PGM_P>(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);
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
/*
|
||||
void drawMeter(int8_t needle){
|
||||
int16_t best, i, s;
|
||||
|
||||
if (needle < 0)
|
||||
return;
|
||||
|
||||
s = (needle * 4)/10;
|
||||
for (i = 0; i < 8; i++){
|
||||
if (s >= 5)
|
||||
lcdMeter[i] = 1;
|
||||
else if (s >= 0)
|
||||
lcdMeter[i] = 2 + s;
|
||||
else
|
||||
lcdMeter[i] = 1;
|
||||
s = s - 5;
|
||||
}
|
||||
if (needle >= 40)
|
||||
lcdMeter[i-1] = 6;
|
||||
lcdMeter[i] = 0;
|
||||
}
|
||||
*/
|
||||
// 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.print(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printLineF(char linenmbr, const __FlashStringHelper *c)
|
||||
{
|
||||
int i;
|
||||
char tmpBuff[17];
|
||||
PGM_P p = reinterpret_cast<PGM_P>(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();
|
||||
}
|
||||
|
||||
//012...89ABC...Z
|
||||
char byteToChar(byte srcByte){
|
||||
if (srcByte < 10)
|
||||
return 0x30 + srcByte;
|
||||
else
|
||||
return 'A' + srcByte - 10;
|
||||
}
|
||||
|
||||
// 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(":");
|
||||
}
|
||||
}
|
||||
|
||||
int enc_prev_state = 3;
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user