Compare commits
14 Commits
working-00
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
9a57ca6ed7 | ||
|
38b696d9c2 | ||
|
cdf3871385 | ||
|
5e675107c1 | ||
|
1a1e92a709 | ||
|
f588a89ee7 | ||
|
20e1eda140 | ||
|
10926b54ec | ||
|
bbf883d3c5 | ||
|
5a6c8308d3 | ||
|
cc78a9f9a1 | ||
|
2f8fe7fb4c | ||
|
262ef3947a | ||
|
a4d9f6e6c5 |
14
README.md
14
README.md
@@ -1,3 +1,17 @@
|
|||||||
|
#KC4UPR update
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
NOTE: This project is no longer maintained. I do not have a uBITX configured to use this code, and so am unable to provide any assistance regarding use of the code. This code is intended for the Raduino (Arduino microcontroller) in the uBITX, and communicates with an additional Teensy 3.2 microcontroller added to the transceiver; without this combination, the code is unlikely to do what you expect. Also, at the point where this project left off, it might or might not have been functional… a hardware failure precluded further testing.
|
||||||
|
|
||||||
|
Some notes about how this works:
|
||||||
|
|
||||||
|
- Requires the ubitx-iop code in the Teensy.
|
||||||
|
- Teensy and Raduino talk via serial (UART).
|
||||||
|
- Teensy provides the CW keyer.
|
||||||
|
- Teensy passes through CAT commands; CAT-handling logic is modified in the Raduino, with a prefix byte to describe whether it's actually CAT data, or other information from the Teensy.
|
||||||
|
- Additional modes are implemented (namely, digimodes and two-tone test).
|
||||||
|
|
||||||
|
Here's the original README.md info from the KD8CEC firmware:
|
||||||
|
|
||||||
#NOTICE
|
#NOTICE
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
- Now Release Version 1.20 on my blog (http://www.hamskey.com)
|
- Now Release Version 1.20 on my blog (http://www.hamskey.com)
|
||||||
|
@@ -56,24 +56,29 @@
|
|||||||
*
|
*
|
||||||
* Send the current mode to the I/O Processor.
|
* Send the current mode to the I/O Processor.
|
||||||
*/
|
*/
|
||||||
void iopSendMode(char cw_mode, char is_usb, char digi_mode, char is_test)
|
void iopSendMode(char cw_mode, char is_usb, char digi_mode)
|
||||||
{
|
{
|
||||||
byte mode;
|
rig_mode mode;
|
||||||
|
|
||||||
if (cw_mode > 0)
|
// NOTE: eventually, add sideband (is_usb) to all of these.
|
||||||
mode = MODE_CW;
|
if (cw_mode > 0) {
|
||||||
else if (digi_mode > 0)
|
mode = rig_mode::cw;
|
||||||
mode = MODE_DIGI;
|
} else if (digi_mode > 0) {
|
||||||
else if (is_test)
|
//mode = (is_usb ? RIG_MODE_DGU : RIG_MODE_DGL);
|
||||||
mode = MODE_TEST;
|
mode = rig_mode::digi;
|
||||||
else
|
// } else if (is_test) {
|
||||||
mode = MODE_SSB;
|
// mode = (is_usb ? RIG_MODE_TTU : RIG_MODE_TTL);
|
||||||
|
} else {
|
||||||
|
mode = rig_mode::ssb; //(is_usb ? usb : lsb);
|
||||||
|
}
|
||||||
sendIOPModeCommand(mode);
|
sendIOPModeCommand(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int skipTimeCount = 0;
|
unsigned int skipTimeCount = 0;
|
||||||
byte CAT_BUFF[5];
|
byte CAT_BUFF[34];
|
||||||
byte CAT_SNDBUFF[5];
|
byte CAT_SNDBUFF[34];
|
||||||
|
|
||||||
|
byte error_buf[17];
|
||||||
|
|
||||||
void SendCatData(byte sendCount)
|
void SendCatData(byte sendCount)
|
||||||
{
|
{
|
||||||
@@ -212,11 +217,11 @@ void CatSetPTT(boolean isPTTOn, byte fromType)
|
|||||||
|
|
||||||
startTx(TX_SSB, 1);
|
startTx(TX_SSB, 1);
|
||||||
//Exit menu, Memory Keyer... ETC
|
//Exit menu, Memory Keyer... ETC
|
||||||
if (isCWAutoMode > 0) {
|
//if (isCWAutoMode > 0) {
|
||||||
isCWAutoMode = 0;
|
// isCWAutoMode = 0;
|
||||||
printLineF2(F("AutoKey Exit/CAT"));
|
// printLineF2(F("AutoKey Exit/CAT"));
|
||||||
//delay_background(1000, 0);
|
// //delay_background(1000, 0);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -279,7 +284,7 @@ void CatSetMode(byte tmpMode, byte fromType)
|
|||||||
digiMode = 1;
|
digiMode = 1;
|
||||||
isUSB = true; // DGU - but need to eventually use the FT-817 customization
|
isUSB = true; // DGU - but need to eventually use the FT-817 customization
|
||||||
}
|
}
|
||||||
iopSendMode(cwMode, isUSB, digiMode, isTest);
|
iopSendMode(cwMode, isUSB, digiMode);
|
||||||
setFrequency(frequency);
|
setFrequency(frequency);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
}
|
}
|
||||||
@@ -810,143 +815,209 @@ byte rxBufferCheckCount = 0;
|
|||||||
//Prevent Stack Overflow
|
//Prevent Stack Overflow
|
||||||
byte isProcessCheck_Cat = 0;
|
byte isProcessCheck_Cat = 0;
|
||||||
|
|
||||||
|
//char iopStatusWindow[4] = " "; // may need to move this if it's not visible to ubitx_lcd_1602
|
||||||
|
char iopMenuDisplay[17] = " ";
|
||||||
|
|
||||||
|
// KC4UPR - these are used to delay the display of the Smeter, if the
|
||||||
|
// IOP status has recently been displayed, to give time to see it.
|
||||||
|
// Put these here because of how Arduino IDE puts .ino files together.
|
||||||
|
//#define SMETER_DELAY_TIME 5000
|
||||||
|
//bool displaySmeter = true;
|
||||||
|
//int delaySmeter;
|
||||||
|
int stateTopLine = 0;
|
||||||
|
|
||||||
//fromType normal : 0, TX : 1, CW_STRAIGHT : 2, CW_PADDLE : 3, CW_AUTOMODE : 4
|
//fromType normal : 0, TX : 1, CW_STRAIGHT : 2, CW_PADDLE : 3, CW_AUTOMODE : 4
|
||||||
//if cw mode, no delay
|
//if cw mode, no delay
|
||||||
void Check_Cat(byte fromType)
|
void Check_Cat(byte fromType)
|
||||||
{
|
{
|
||||||
byte i;
|
byte i;
|
||||||
|
|
||||||
|
static PrefixID readPrefix;
|
||||||
|
static uint8_t readLength;
|
||||||
|
static IOPMessage msg;
|
||||||
|
static bool read_in_progress = false;
|
||||||
|
|
||||||
//Check Serial Port Buffer
|
//Check Serial Port Buffer
|
||||||
if (Serial.available() == 0)
|
if (Serial.available() == 0 && !read_in_progress)
|
||||||
{
|
{
|
||||||
//Set Buffer Clear status
|
//Set Buffer Clear status
|
||||||
rxBufferCheckCount = 0;
|
//rxBufferCheckCount = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (Serial.available() < 5)
|
// KC4UPR - IOP update: changed this to 6 characters, because we're going to have a
|
||||||
|
// first character which defines if this is CAT or IOP.
|
||||||
|
else // if (Serial.available() < 6) //5)
|
||||||
{
|
{
|
||||||
//First Arrived
|
if (!read_in_progress) {
|
||||||
if (rxBufferCheckCount == 0)
|
byte first = Serial.read();
|
||||||
{
|
readPrefix = byteToPrefix(first);
|
||||||
rxBufferCheckCount = Serial.available();
|
readLength = byteToLength(first);
|
||||||
rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT; //Set time for timeout
|
|
||||||
}
|
|
||||||
else if (rxBufferArriveTime < millis()) //timeout
|
|
||||||
{
|
|
||||||
//Clear Buffer
|
|
||||||
for (i = 0; i < Serial.available(); i++)
|
|
||||||
rxBufferCheckCount = Serial.read();
|
|
||||||
|
|
||||||
rxBufferCheckCount = 0;
|
|
||||||
}
|
|
||||||
else if (rxBufferCheckCount < Serial.available()) //increase buffer count, slow arrived
|
|
||||||
{
|
|
||||||
rxBufferCheckCount = Serial.available();
|
rxBufferCheckCount = Serial.available();
|
||||||
rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT; //Set time for timeout
|
rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT;
|
||||||
|
|
||||||
|
read_in_progress = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Serial.available() < readLength) { // not ready to read everything yet (not enough bytes)
|
||||||
|
|
||||||
|
if (rxBufferCheckCount < Serial.available()) { // increase buffer count, slow arrival
|
||||||
|
rxBufferCheckCount = Serial.available();
|
||||||
|
rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT; // update time for timeout
|
||||||
|
|
||||||
|
} else if (rxBufferArriveTime < millis()) { // timeout, so clear buffer
|
||||||
|
for (i = 0; i < Serial.available(); i++)
|
||||||
|
rxBufferCheckCount = Serial.read();
|
||||||
|
rxBufferCheckCount = 0;
|
||||||
|
read_in_progress = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < readLength; i++) {
|
||||||
|
CAT_BUFF[i] = Serial.read();
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Arived CAT DATA
|
// KC4UPR: I don't understand why this is here or how/when it will ever get called, but I will leave
|
||||||
for (i = 0; i < 5; i++)
|
// it alone for now.
|
||||||
CAT_BUFF[i] = Serial.read();
|
|
||||||
|
|
||||||
if (isProcessCheck_Cat == 1)
|
if (isProcessCheck_Cat == 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
isProcessCheck_Cat = 1;
|
isProcessCheck_Cat = 1;
|
||||||
|
|
||||||
//reference : http://www.ka7oei.com/ft817_meow.html
|
if (readPrefix == IOP_PREFIX) {
|
||||||
switch(CAT_BUFF[4])
|
recvIOPMessage(msg, CAT_BUFF, readLength); // not super robust... if IOP ever sends more (or less) than a 5 (6) byte message
|
||||||
{
|
// following assumes it's a status message, 4 chars (including trailing null, which I'm ignoring...
|
||||||
//The stability has not been verified and there seems to be no need. so i remarked codes,
|
switch(msg.id) {
|
||||||
//if you need, unmark lines
|
/*case IOP_SSB_STATUS_MSG:
|
||||||
/*
|
case IOP_DGT_STATUS_MSG:
|
||||||
case 0x00 : //Lock On
|
case IOP_CW_STATUS_MSG:
|
||||||
if (isDialLock == 1) //This command returns 00 if it was unlocked, and F0 if already locked.
|
case IOP_TEST_STATUS_MSG:
|
||||||
CAT_BUFF[0] = 0xF0;
|
iopStatusWindow[0] = msg.data[0];
|
||||||
else {
|
iopStatusWindow[1] = msg.data[1];
|
||||||
CAT_BUFF[0] = 0x00;
|
iopStatusWindow[2] = msg.data[2];
|
||||||
setDialLock(1, fromType);
|
displaySmeter = false;
|
||||||
}
|
delaySmeter = millis() + SMETER_DELAY_TIME;
|
||||||
Serial.write(CAT_BUFF[0]); //Time
|
break;*/
|
||||||
|
|
||||||
|
case IOP_MODE_REQUEST:
|
||||||
|
iopSendMode(cwMode, isUSB, digiMode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOP_MENU_DISPLAY_MSG:
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
iopMenuDisplay[i] = msg.data[i];
|
||||||
|
}
|
||||||
|
stateTopLine = 2;
|
||||||
|
sprintf(error_buf, "# recv'd: %3d", readLength);
|
||||||
|
sendIOPDebugMessage(error_buf);
|
||||||
|
sendIOPDebugMessage(iopMenuDisplay);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOP_MENU_INACTIVE_MSG:
|
||||||
|
stateTopLine = 0;
|
||||||
|
line2DisplayStatus = 0; // trying to force an update
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (readPrefix == CAT_PREFIX) {
|
||||||
|
|
||||||
|
//reference : http://www.ka7oei.com/ft817_meow.html
|
||||||
|
switch(CAT_BUFF[4])
|
||||||
|
{
|
||||||
|
//The stability has not been verified and there seems to be no need. so i remarked codes,
|
||||||
|
//if you need, unmark lines
|
||||||
|
/*
|
||||||
|
case 0x00 : //Lock On
|
||||||
|
if (isDialLock == 1) //This command returns 00 if it was unlocked, and F0 if already locked.
|
||||||
|
CAT_BUFF[0] = 0xF0;
|
||||||
|
else {
|
||||||
|
CAT_BUFF[0] = 0x00;
|
||||||
|
setDialLock(1, fromType);
|
||||||
|
}
|
||||||
|
Serial.write(CAT_BUFF[0]); //Time
|
||||||
|
break;
|
||||||
|
case 0x80 : //Lock Off
|
||||||
|
if (isDialLock == 0) //This command returns 00 if the '817 was already locked, and F0 (HEX) if already unlocked.
|
||||||
|
CAT_BUFF[0] = 0xF0;
|
||||||
|
else {
|
||||||
|
CAT_BUFF[0] = 0x00;
|
||||||
|
setDialLock(0, fromType);
|
||||||
|
}
|
||||||
|
Serial.write(CAT_BUFF[0]); //Time
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
|
||||||
|
case 0x01 : //Set Frequency
|
||||||
|
CatSetFreq(fromType);
|
||||||
break;
|
break;
|
||||||
case 0x80 : //Lock Off
|
|
||||||
if (isDialLock == 0) //This command returns 00 if the '817 was already locked, and F0 (HEX) if already unlocked.
|
case 0x02 : //Split On
|
||||||
CAT_BUFF[0] = 0xF0;
|
case 0x82: //Split Off
|
||||||
else {
|
CatSetSplit(CAT_BUFF[4] == 0x02);
|
||||||
CAT_BUFF[0] = 0x00;
|
|
||||||
setDialLock(0, fromType);
|
|
||||||
}
|
|
||||||
Serial.write(CAT_BUFF[0]); //Time
|
|
||||||
break;
|
break;
|
||||||
*/
|
|
||||||
|
case 0x03 : //Read Frequency and mode
|
||||||
case 0x01 : //Set Frequency
|
CatGetFreqMode(frequency);
|
||||||
CatSetFreq(fromType);
|
break;
|
||||||
break;
|
|
||||||
|
case 0x07 : //Set Operating Mode
|
||||||
case 0x02 : //Split On
|
CatSetMode(CAT_BUFF[0], fromType);
|
||||||
case 0x82: //Split Off
|
break;
|
||||||
CatSetSplit(CAT_BUFF[4] == 0x02);
|
|
||||||
break;
|
case 0x08 : //Set PTT_ON
|
||||||
|
case 0x88: //Set PTT Off
|
||||||
case 0x03 : //Read Frequency and mode
|
CatSetPTT(CAT_BUFF[4] == 0x08, fromType);
|
||||||
CatGetFreqMode(frequency);
|
break;
|
||||||
break;
|
|
||||||
|
case 0x81: //Toggle VFO
|
||||||
case 0x07 : //Set Operating Mode
|
CatVFOToggle(true, fromType);
|
||||||
CatSetMode(CAT_BUFF[0], fromType);
|
break;
|
||||||
break;
|
|
||||||
|
case 0xDB: //Read uBITX EEPROM Data
|
||||||
case 0x08 : //Set PTT_ON
|
ReadEEPRom(); //Call by uBITX Manager Program
|
||||||
case 0x88: //Set PTT Off
|
break;
|
||||||
CatSetPTT(CAT_BUFF[4] == 0x08, fromType);
|
case 0xBB: //Read FT-817 EEPROM Data (for comfirtable)
|
||||||
break;
|
ReadEEPRom_FT817();
|
||||||
|
break;
|
||||||
case 0x81: //Toggle VFO
|
|
||||||
CatVFOToggle(true, fromType);
|
case 0xDC: //Write uBITX EEPROM Data
|
||||||
break;
|
WriteEEPRom(); //Call by uBITX Manager Program
|
||||||
|
break;
|
||||||
case 0xDB: //Read uBITX EEPROM Data
|
case 0xBC: //Write FT-817 EEPROM Data (for comfirtable)
|
||||||
ReadEEPRom(); //Call by uBITX Manager Program
|
WriteEEPRom_FT817(fromType);
|
||||||
break;
|
break;
|
||||||
case 0xBB: //Read FT-817 EEPROM Data (for comfirtable)
|
|
||||||
ReadEEPRom_FT817();
|
case 0xDD: //Read uBITX ADC Data
|
||||||
break;
|
ReadADCValue(); //Call by uBITX Manager Program
|
||||||
|
break;
|
||||||
case 0xDC: //Write uBITX EEPROM Data
|
|
||||||
WriteEEPRom(); //Call by uBITX Manager Program
|
case 0xDE: //IF-Shift Control by CAT
|
||||||
break;
|
SetIFSValue(); //
|
||||||
case 0xBC: //Write FT-817 EEPROM Data (for comfirtable)
|
break;
|
||||||
WriteEEPRom_FT817(fromType);
|
|
||||||
break;
|
case 0xE7 : //Read RX Status
|
||||||
|
CatRxStatus();
|
||||||
case 0xDD: //Read uBITX ADC Data
|
break;
|
||||||
ReadADCValue(); //Call by uBITX Manager Program
|
case 0xF7: //Read TX Status
|
||||||
break;
|
CatTxStatus();
|
||||||
|
break;
|
||||||
case 0xDE: //IF-Shift Control by CAT
|
default:
|
||||||
SetIFSValue(); //
|
/*
|
||||||
break;
|
char buff[16];
|
||||||
|
sprintf(buff, "DEFAULT : %x", CAT_BUFF[4]);
|
||||||
case 0xE7 : //Read RX Status
|
printLine2(buff);
|
||||||
CatRxStatus();
|
*/
|
||||||
break;
|
Serial.write(ACK);
|
||||||
case 0xF7: //Read TX Status
|
break;
|
||||||
CatTxStatus();
|
} //end of switch
|
||||||
break;
|
}
|
||||||
default:
|
|
||||||
/*
|
|
||||||
char buff[16];
|
|
||||||
sprintf(buff, "DEFAULT : %x", CAT_BUFF[4]);
|
|
||||||
printLine2(buff);
|
|
||||||
*/
|
|
||||||
Serial.write(ACK);
|
|
||||||
break;
|
|
||||||
} //end of switch
|
|
||||||
|
|
||||||
isProcessCheck_Cat = 0;
|
isProcessCheck_Cat = 0;
|
||||||
|
read_in_progress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init_Cat(long baud, int portConfig)
|
void Init_Cat(long baud, int portConfig)
|
||||||
@@ -956,5 +1027,6 @@ void Init_Cat(long baud, int portConfig)
|
|||||||
|
|
||||||
// At start, immediately send mode to IOP. Currently, IOP has no way to
|
// At start, immediately send mode to IOP. Currently, IOP has no way to
|
||||||
// request the mode.
|
// request the mode.
|
||||||
iopSendMode(cwMode, isUSB, digiMode, isTest);
|
// Moving this to main setup loop. Here, it may actually occur before the Raduino knows its mode!
|
||||||
|
//iopSendMode(cwMode, isUSB, digiMode, isTest);
|
||||||
}
|
}
|
||||||
|
@@ -1,400 +0,0 @@
|
|||||||
/*************************************************************************
|
|
||||||
KD8CEC's Memory Keyer for HAM
|
|
||||||
|
|
||||||
This source code is written for All amateur radio operator,
|
|
||||||
I have not had amateur radio communication for a long time. CW has been
|
|
||||||
around for a long time, and I do not know what kind of keyer and keying
|
|
||||||
software is fashionable. So I implemented the functions I need mainly.
|
|
||||||
|
|
||||||
To minimize the use of memory space, we used bitwise operations.
|
|
||||||
For the alphabet, I put Morsecode in 1 byte. The front 4Bit is the length
|
|
||||||
and the 4Bit is the Morse code. Because the number is fixed in length,
|
|
||||||
there is no separate length information. The 5Bit on the right side is
|
|
||||||
the Morse code.
|
|
||||||
|
|
||||||
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
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
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/>.
|
|
||||||
|
|
||||||
**************************************************************************/
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
||||||
//27 + 10 + 18 + 1(SPACE) = //56
|
|
||||||
const PROGMEM uint8_t cwAZTable[27] = {0b00100100 , 0b01001000 , 0b01001010 , 0b00111000 , 0b00010000, 0b01000010, 0b00111100, 0b01000000 , //A ~ H
|
|
||||||
0b00100000, 0b01000111 ,0b00111010, 0b01000100, 0b00101100, 0b00101000 , 0b00111110, 0b01000110, 0b01001101, 0b00110100, //I ~ R
|
|
||||||
0b00110000, 0b00011000, 0b00110010, 0b01000001, 0b00110110, 0b01001001, 0b01001011, 0b01001100}; //S ~ Z
|
|
||||||
PGM_P pCwAZTable = reinterpret_cast<PGM_P>(cwAZTable);
|
|
||||||
|
|
||||||
const PROGMEM uint8_t cw09Table[27] = {0b00011111, 0b00001111, 0b00000111, 0b00000011, 0b00000001, 0b00000000, 0b00010000, 0b00011000, 0b00011100, 0b00011110};
|
|
||||||
PGM_P pcw09Table = reinterpret_cast<PGM_P>(cw09Table);
|
|
||||||
|
|
||||||
//# : AR, ~:BT, [:AS, ]:SK, ^:KN
|
|
||||||
const PROGMEM uint8_t cwSymbolIndex[] = {'.', ',', '?', '"', '!', '/', '(', ')', '&', ':', ';', '=', '+', '-', '_', '\'', '@', '#', '~', '[', ']', '^' };
|
|
||||||
PGM_P pCwSymbolIndex = reinterpret_cast<PGM_P>(cwSymbolIndex);
|
|
||||||
|
|
||||||
const PROGMEM uint8_t cwSymbolTable[] = {0b11010101, 0b11110011, 0b11001100, 0b11011110, 0b11101011, 0b10100100, 0b10101100, 0b11101101, 0b10010000, 0b11111000, 0b11101010, 0b10100010, 0b10010100, 0b11100001, 0b11001101, 0b11010010, 0b11011010, 0b10010100, 0b10100010, 0b10010000, 0b11000101, 0b10101100};
|
|
||||||
PGM_P pCwSymbolTable = reinterpret_cast<PGM_P>(cwSymbolTable);
|
|
||||||
////const PROGMEM uint8_t cwSymbolLength[] = {6, 6, 6, 6, 6, 5, 5, 6, 5, 6, 6, 5, 5, 6, 6, 6, 6, 5, 5, 5, 6, 5};
|
|
||||||
|
|
||||||
// ":(Start"), ':(End "), >: My callsign, <:QSO Callsign (Second Callsign), #:AR, ~:BT, [:AS, ]:SK
|
|
||||||
|
|
||||||
byte knobPosition = 0;
|
|
||||||
//byte cwTextData[30]; //Maximum 30 Remarked by KD8CE -> Direct Read EEPROM
|
|
||||||
byte autoCWSendCharEndIndex = 0;
|
|
||||||
byte autoCWSendCharIndex = 0;
|
|
||||||
unsigned long autoCWbeforeTime = 0; //for interval time between chars
|
|
||||||
byte pttBeforeStatus = 1; //PTT : default high
|
|
||||||
byte isKeyStatusAfterCWStart = 0; //0 : Init, 1 : Keyup after auto CW Start, 2 : Keydown after
|
|
||||||
byte selectedCWTextIndex = 0;
|
|
||||||
unsigned long autoCWKeydownCheckTime = 0; //for interval time between chars
|
|
||||||
byte changeReserveStatus = 0;
|
|
||||||
byte isAutoCWHold = 0; //auto CW Pause => Manual Keying => auto
|
|
||||||
|
|
||||||
void autoSendPTTCheck()
|
|
||||||
{
|
|
||||||
if (isCWAutoMode == 2) { //Sending Mode
|
|
||||||
//check PTT Button
|
|
||||||
//short Press => reservation or cancel
|
|
||||||
//long Press => Hold
|
|
||||||
if (digitalRead(PTT) == LOW)
|
|
||||||
{
|
|
||||||
//if (isKeyStatusAfterCWStart == 0) //Yet Press PTT from start TX
|
|
||||||
//{
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (isKeyStatusAfterCWStart == 1) //while auto cw send, ptt up and ptt down again
|
|
||||||
{
|
|
||||||
//Start Time
|
|
||||||
autoCWKeydownCheckTime = millis() + 200; //Long push time
|
|
||||||
isKeyStatusAfterCWStart = 2; //Change status => ptt down agian
|
|
||||||
}
|
|
||||||
else if (isKeyStatusAfterCWStart == 2 && autoCWKeydownCheckTime < millis())
|
|
||||||
{
|
|
||||||
//Hold Mode
|
|
||||||
isAutoCWHold = 1;
|
|
||||||
isKeyStatusAfterCWStart = 3;
|
|
||||||
}
|
|
||||||
else if (isKeyStatusAfterCWStart == 3)
|
|
||||||
{
|
|
||||||
autoCWKeydownCheckTime = millis() + 200;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//PTT UP
|
|
||||||
if (isKeyStatusAfterCWStart == 2) //0 (down before cw start) -> 1 (up while cw sending) -> 2 (down while cw sending)
|
|
||||||
{
|
|
||||||
if (autoCWKeydownCheckTime > millis()) //Short : Reservation or cancel Next Text
|
|
||||||
{
|
|
||||||
if (autoCWSendReservCount == 0 ||
|
|
||||||
(autoCWSendReservCount < AUTO_CW_RESERVE_MAX &&
|
|
||||||
autoCWSendReserv[autoCWSendReservCount - 1] != selectedCWTextIndex))
|
|
||||||
{
|
|
||||||
//Reserve
|
|
||||||
autoCWSendReserv[autoCWSendReservCount++] = selectedCWTextIndex;
|
|
||||||
changeReserveStatus = 1;
|
|
||||||
}
|
|
||||||
else if (autoCWSendReservCount > 0 && autoCWSendReserv[autoCWSendReservCount - 1] == selectedCWTextIndex)
|
|
||||||
{
|
|
||||||
autoCWSendReservCount--;
|
|
||||||
changeReserveStatus = 1;
|
|
||||||
}
|
|
||||||
} // end of Short Key up
|
|
||||||
}
|
|
||||||
else if (isKeyStatusAfterCWStart == 3) //play from Hold (pause Auto CW Send)
|
|
||||||
{
|
|
||||||
isAutoCWHold = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
isKeyStatusAfterCWStart = 1; //Change status => ptt up (while cw send mode)
|
|
||||||
} //end of PTT UP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Send 1 char
|
|
||||||
void sendCWChar(char cwKeyChar)
|
|
||||||
{
|
|
||||||
byte sendBuff[7];
|
|
||||||
byte i, j, charLength;
|
|
||||||
byte tmpChar;
|
|
||||||
|
|
||||||
//For Macrofunction
|
|
||||||
//replace > and < to My callsign, qso callsign, use recursive function call
|
|
||||||
if (cwKeyChar == '>' || cwKeyChar == '<')
|
|
||||||
{
|
|
||||||
uint16_t callsignStartIndex = 0;
|
|
||||||
uint16_t callsignEndIndex = 0;
|
|
||||||
|
|
||||||
if (cwKeyChar == '>') //replace my callsign
|
|
||||||
{
|
|
||||||
if (userCallsignLength > 0)
|
|
||||||
{
|
|
||||||
callsignStartIndex = 0;
|
|
||||||
callsignEndIndex = userCallsignLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (cwKeyChar == '<') //replace qso callsign
|
|
||||||
{
|
|
||||||
//ReadLength
|
|
||||||
callsignEndIndex = EEPROM.read(CW_STATION_LEN);
|
|
||||||
if (callsignEndIndex > 0)
|
|
||||||
{
|
|
||||||
callsignStartIndex = CW_STATION_LEN - callsignEndIndex - USER_CALLSIGN_DAT;
|
|
||||||
callsignEndIndex = callsignStartIndex + callsignEndIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callsignStartIndex == 0 && callsignEndIndex == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (uint16_t i = callsignStartIndex; i <= callsignEndIndex; i++)
|
|
||||||
{
|
|
||||||
sendCWChar(EEPROM.read(USER_CALLSIGN_DAT + i));
|
|
||||||
autoSendPTTCheck(); //for reserve and cancel next CW Text
|
|
||||||
if (changeReserveStatus == 1)
|
|
||||||
{
|
|
||||||
changeReserveStatus = 0;
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < callsignEndIndex) delay_background(cwSpeed * 3, 4); //
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (cwKeyChar >= 'A' && cwKeyChar <= 'Z') //Encode Char by KD8CEC
|
|
||||||
{
|
|
||||||
tmpChar = pgm_read_byte(pCwAZTable + (cwKeyChar - 'A'));
|
|
||||||
charLength = (tmpChar >> 4) & 0x0F;
|
|
||||||
for (i = 0; i < charLength; i++)
|
|
||||||
sendBuff[i] = (tmpChar << i) & 0x08;
|
|
||||||
}
|
|
||||||
else if (cwKeyChar >= '0' && cwKeyChar <= '9')
|
|
||||||
{
|
|
||||||
charLength = 5;
|
|
||||||
for (i = 0; i < charLength; i++)
|
|
||||||
sendBuff[i] = (pgm_read_byte(pcw09Table + (cwKeyChar - '0')) << i) & 0x10;
|
|
||||||
}
|
|
||||||
else if (cwKeyChar == ' ')
|
|
||||||
{
|
|
||||||
charLength = 0;
|
|
||||||
delay_background(cwSpeed * 4, 4); //7 -> basic interval is 3
|
|
||||||
}
|
|
||||||
else if (cwKeyChar == '$') //7 digit
|
|
||||||
{
|
|
||||||
charLength = 7;
|
|
||||||
for (i = 0; i < 7; i++)
|
|
||||||
sendBuff[i] = (0b00010010 << i) & 0x80; //...1..1
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//symbol
|
|
||||||
for (i = 0; i < 22; i++)
|
|
||||||
{
|
|
||||||
if (pgm_read_byte(pCwSymbolIndex + i) == cwKeyChar)
|
|
||||||
{
|
|
||||||
tmpChar = pgm_read_byte(pCwSymbolTable + i);
|
|
||||||
charLength = ((tmpChar >> 6) & 0x03) + 3;
|
|
||||||
|
|
||||||
for (j = 0; j < charLength; j++)
|
|
||||||
sendBuff[j] = (tmpChar << (j + 2)) & 0x80;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
charLength = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < charLength; i++)
|
|
||||||
{
|
|
||||||
cwKeydown();
|
|
||||||
if (sendBuff[i] == 0)
|
|
||||||
delay_background(cwSpeed, 4);
|
|
||||||
else
|
|
||||||
delay_background(cwSpeed * 3, 4);
|
|
||||||
cwKeyUp();
|
|
||||||
if (i != charLength -1)
|
|
||||||
delay_background(cwSpeed, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte isNeedScroll = 0;
|
|
||||||
unsigned long scrollDispayTime = 0;
|
|
||||||
#define scrollSpeed 500
|
|
||||||
byte displayScrolStep = 0;
|
|
||||||
|
|
||||||
void controlAutoCW(){
|
|
||||||
int knob = 0;
|
|
||||||
byte i;
|
|
||||||
|
|
||||||
byte cwStartIndex, cwEndIndex;
|
|
||||||
|
|
||||||
if (cwAutoDialType == 0)
|
|
||||||
knob = enc_read();
|
|
||||||
|
|
||||||
if (knob != 0 || beforeCWTextIndex == 255 || isNeedScroll == 1){ //start display
|
|
||||||
if (knobPosition > 0 && knob < 0)
|
|
||||||
knobPosition--;
|
|
||||||
if (knobPosition < cwAutoTextCount * 10 -1 && knob > 0)
|
|
||||||
knobPosition++;
|
|
||||||
|
|
||||||
selectedCWTextIndex = knobPosition / 10;
|
|
||||||
|
|
||||||
if ((beforeCWTextIndex != selectedCWTextIndex) ||
|
|
||||||
(isNeedScroll == 1 && beforeCWTextIndex == selectedCWTextIndex && scrollDispayTime < millis())) {
|
|
||||||
//Read CW Text Data Position From EEProm
|
|
||||||
EEPROM.get(CW_AUTO_DATA + (selectedCWTextIndex * 2), cwStartIndex);
|
|
||||||
EEPROM.get(CW_AUTO_DATA + (selectedCWTextIndex * 2 + 1), cwEndIndex);
|
|
||||||
|
|
||||||
if (beforeCWTextIndex == selectedCWTextIndex)
|
|
||||||
{
|
|
||||||
if (++displayScrolStep > cwEndIndex - cwStartIndex)
|
|
||||||
displayScrolStep = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
displayScrolStep = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_SW_SERIAL
|
|
||||||
//Not need Scroll
|
|
||||||
//Display_AutoKeyTextIndex(selectedCWTextIndex);
|
|
||||||
SendCommand1Num('w', selectedCWTextIndex); //Index
|
|
||||||
SendEEPromData('a', cwStartIndex + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ, 0) ; //Data
|
|
||||||
SendCommand1Num('y', 1); //Send YN
|
|
||||||
isNeedScroll = 0;
|
|
||||||
#else
|
|
||||||
printLineFromEEPRom(0, 2, cwStartIndex + displayScrolStep + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ, 0);
|
|
||||||
isNeedScroll = (cwEndIndex - cwStartIndex) > 14 ? 1 : 0;
|
|
||||||
Display_AutoKeyTextIndex(selectedCWTextIndex);
|
|
||||||
#endif
|
|
||||||
scrollDispayTime = millis() + scrollSpeed;
|
|
||||||
beforeCWTextIndex = selectedCWTextIndex;
|
|
||||||
}
|
|
||||||
} //end of check knob
|
|
||||||
|
|
||||||
if (isCWAutoMode == 1) { //ready status
|
|
||||||
if (digitalRead(PTT) == LOW) //PTT Down : Start Auto CW or DialMode Change
|
|
||||||
{
|
|
||||||
if (pttBeforeStatus == 1) //High to Low Change
|
|
||||||
{
|
|
||||||
autoCWbeforeTime = millis() + 500; //Long push time
|
|
||||||
pttBeforeStatus = 0;
|
|
||||||
}
|
|
||||||
else if (autoCWbeforeTime < millis()) //while press PTT, OK Long push then Send Auto CW Text
|
|
||||||
{
|
|
||||||
sendingCWTextIndex = selectedCWTextIndex;
|
|
||||||
|
|
||||||
//Information about Auto Send CW Text
|
|
||||||
autoCWSendCharEndIndex = cwEndIndex; //length of CW Text //ianlee
|
|
||||||
autoCWSendCharIndex = cwStartIndex; //position of Sending Char //ianlee
|
|
||||||
|
|
||||||
isCWAutoMode = 2; //auto sending start
|
|
||||||
autoCWbeforeTime = 0; //interval between chars, 0 = always send
|
|
||||||
isKeyStatusAfterCWStart = 0; //Init PTT Key status
|
|
||||||
autoCWSendReservCount = 0; //Init Reserve Count
|
|
||||||
isAutoCWHold = 0;
|
|
||||||
if (!inTx){ //if not TX Status, change RX -> TX
|
|
||||||
keyDown = 0;
|
|
||||||
startTx(TX_CW, 0); //disable updateDisplay Command for reduce latency time
|
|
||||||
updateDisplay();
|
|
||||||
|
|
||||||
delay_background(delayBeforeCWStartTime * 2, 2); //for External AMP or personal situation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pttBeforeStatus == 0 && autoCWbeforeTime > 0) //while reade status LOW -> HIGH (before Auto send Before)
|
|
||||||
{
|
|
||||||
pttBeforeStatus = 1; //HIGH
|
|
||||||
if (autoCWbeforeTime > millis()) //short Press -> ? DialModeChange
|
|
||||||
{
|
|
||||||
cwAutoDialType = (cwAutoDialType == 1 ? 0 : 1); //Invert DialMode between select CW Text and Frequency Tune
|
|
||||||
if (cwAutoDialType == 0)
|
|
||||||
printLineF1(F("Dial:Select Text"));
|
|
||||||
else
|
|
||||||
printLineF1(F("Dial:Freq Tune"));
|
|
||||||
|
|
||||||
delay_background(1000, 0);
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} //end of isCWAutoMode == 1 condition
|
|
||||||
|
|
||||||
if (isCWAutoMode == 2) { //Sending Mode
|
|
||||||
autoSendPTTCheck();
|
|
||||||
|
|
||||||
//check interval time, if you want adjust interval between chars, modify below
|
|
||||||
if (isAutoCWHold == 0 && (millis() - autoCWbeforeTime > cwSpeed * 3))
|
|
||||||
{
|
|
||||||
if (!inTx){ //if not TX Status, change RX -> TX
|
|
||||||
keyDown = 0;
|
|
||||||
startTx(TX_CW, 0); //disable updateDisplay Command for reduce latency time
|
|
||||||
}
|
|
||||||
|
|
||||||
sendCWChar(EEPROM.read(CW_AUTO_DATA + autoCWSendCharIndex++));
|
|
||||||
|
|
||||||
if (autoCWSendCharIndex > autoCWSendCharEndIndex) { //finish auto cw send
|
|
||||||
//check reserve status
|
|
||||||
if (autoCWSendReservCount > 0)
|
|
||||||
{
|
|
||||||
//prepare
|
|
||||||
sendingCWTextIndex = autoCWSendReserv[0];
|
|
||||||
|
|
||||||
for (i = 0; i < AUTO_CW_RESERVE_MAX -1; i++)
|
|
||||||
autoCWSendReserv[i] = autoCWSendReserv[i + 1];
|
|
||||||
|
|
||||||
EEPROM.get(CW_AUTO_DATA + (sendingCWTextIndex * 2), cwStartIndex);
|
|
||||||
EEPROM.get(CW_AUTO_DATA + (sendingCWTextIndex * 2 + 1), cwEndIndex);
|
|
||||||
|
|
||||||
//Information about Auto Send CW Text
|
|
||||||
autoCWSendCharEndIndex = cwEndIndex; //length of CW Text //ianlee
|
|
||||||
autoCWSendCharIndex = cwStartIndex; //position of Sending Char //ianlee
|
|
||||||
autoCWSendReservCount--; //Decrease
|
|
||||||
|
|
||||||
sendCWChar(' '); //APPLY SPACE between CW Texts
|
|
||||||
changeReserveStatus = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isCWAutoMode = 1; //ready status
|
|
||||||
delay_background(cwDelayTime * 10, 2);
|
|
||||||
stopTx();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
autoCWbeforeTime = millis();
|
|
||||||
|
|
||||||
if (changeReserveStatus == 1)
|
|
||||||
{
|
|
||||||
changeReserveStatus = 0;
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//abort if this button is down
|
|
||||||
if (btnDown())
|
|
||||||
{
|
|
||||||
isCWAutoMode = 0; //dsiable Auto CW Mode
|
|
||||||
printLine2ClearAndUpdate();
|
|
||||||
delay_background(1000, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,334 +0,0 @@
|
|||||||
/*
|
|
||||||
Softserial for Nextion LCD and Control MCU
|
|
||||||
KD8CEC, Ian Lee
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
It is a library rewritten in C format based on SoftwareSerial.c.
|
|
||||||
I tried to use as much as possible without modifying the SoftwareSerial.
|
|
||||||
But eventually I had to modify the code.
|
|
||||||
|
|
||||||
I rewrote it in C for the following reasons.
|
|
||||||
- Problems occurred when increasing Program Size and Program Memory
|
|
||||||
- We had to reduce the program size.
|
|
||||||
Of course, Software Serial is limited to one.
|
|
||||||
- reduce the steps for transmitting and receiving
|
|
||||||
|
|
||||||
useage
|
|
||||||
extern void SWSerial_Begin(long speedBaud);
|
|
||||||
extern void SWSerial_Write(uint8_t b);
|
|
||||||
extern int SWSerial_Available(void);
|
|
||||||
extern int SWSerial_Read(void);
|
|
||||||
extern void SWSerial_Print(uint8_t *b);
|
|
||||||
|
|
||||||
If you use Softwreserial library instead of this library, you can modify the code as shown below.
|
|
||||||
I kept the function name of SoftwareSerial so you only need to modify a few lines of code.
|
|
||||||
|
|
||||||
define top of source code
|
|
||||||
#include <SoftwareSerial.h>
|
|
||||||
SoftwareSerial sSerial(10, 11); // RX, TX
|
|
||||||
|
|
||||||
replace source code
|
|
||||||
SWSerial_Begin to sSerial.begin
|
|
||||||
SWSerial_Write to sSerial.write
|
|
||||||
SWSerial_Available to sSerial.available
|
|
||||||
SWSerial_Read to sSerial.read
|
|
||||||
|
|
||||||
KD8CEC, Ian Lee
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
All licenses for the source code are subject to the license of the original source SoftwareSerial Library.
|
|
||||||
However, if you use or modify this code, please keep the all comments in this source code.
|
|
||||||
KD8CEC
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
License from SoftwareSerial
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
SoftwareSerial.cpp (formerly NewSoftSerial.cpp) -
|
|
||||||
Multi-instance software serial library for Arduino/Wiring
|
|
||||||
-- Interrupt-driven receive and other improvements by ladyada
|
|
||||||
(http://ladyada.net)
|
|
||||||
-- Tuning, circular buffer, derivation from class Print/Stream,
|
|
||||||
multi-instance support, porting to 8MHz processors,
|
|
||||||
various optimizations, PROGMEM delay tables, inverse logic and
|
|
||||||
direct port writing by Mikal Hart (http://www.arduiniana.org)
|
|
||||||
-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
|
|
||||||
-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
|
|
||||||
-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
The latest version of this library can always be found at
|
|
||||||
http://arduiniana.org.
|
|
||||||
*/
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
//================================================================
|
|
||||||
//Public Variable
|
|
||||||
//================================================================
|
|
||||||
#define TX_PIN 9
|
|
||||||
#define RX_PIN 8
|
|
||||||
#define _SS_MAX_RX_BUFF 35 // RX buffer size
|
|
||||||
#define PRINT_MAX_LENGTH 30
|
|
||||||
|
|
||||||
//================================================================
|
|
||||||
//Internal Variable from SoftwareSerial.c and SoftwareSerial.h
|
|
||||||
//================================================================
|
|
||||||
//variable from softwareserial.c and softwareserial.h
|
|
||||||
static uint8_t swr_receive_buffer[_SS_MAX_RX_BUFF];
|
|
||||||
|
|
||||||
volatile uint8_t *_transmitPortRegister; //Write Port Register
|
|
||||||
uint8_t transmit_RegMask; //use Mask bit 1
|
|
||||||
uint8_t transmit_InvMask; //use mask bit 0
|
|
||||||
|
|
||||||
volatile uint8_t *_receivePortRegister; //Read Port Register
|
|
||||||
uint8_t _receiveBitMask;
|
|
||||||
|
|
||||||
//delay value for Bit
|
|
||||||
uint16_t _tx_delay;
|
|
||||||
|
|
||||||
//delay value for Receive
|
|
||||||
uint16_t _rx_delay_stopbit;
|
|
||||||
uint16_t _rx_delay_centering;
|
|
||||||
uint16_t _rx_delay_intrabit;
|
|
||||||
|
|
||||||
//Customize for uBITX Protocol
|
|
||||||
int8_t receiveIndex = 0;
|
|
||||||
uint8_t receivedCommandLength = 0;
|
|
||||||
int8_t ffCount = 0;
|
|
||||||
|
|
||||||
//Values for Receive Buffer
|
|
||||||
//uint16_t _buffer_overflow;
|
|
||||||
//static volatile uint8_t _receive_buffer_head;
|
|
||||||
//static volatile uint8_t _receive_buffer_tail;
|
|
||||||
|
|
||||||
//Values for Interrupt (check Start Bit)
|
|
||||||
volatile uint8_t *_pcint_maskreg;
|
|
||||||
uint8_t _pcint_maskvalue;
|
|
||||||
|
|
||||||
//================================================================
|
|
||||||
//Internal Function from SoftwareSerial.c
|
|
||||||
//================================================================
|
|
||||||
uint16_t subtract_cap(uint16_t num, uint16_t sub)
|
|
||||||
{
|
|
||||||
if (num > sub)
|
|
||||||
return num - sub;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void tunedDelay(uint16_t delay)
|
|
||||||
{
|
|
||||||
_delay_loop_2(delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRxIntMsk(bool enable)
|
|
||||||
{
|
|
||||||
if (enable)
|
|
||||||
*_pcint_maskreg |= _pcint_maskvalue;
|
|
||||||
else
|
|
||||||
*_pcint_maskreg &= ~_pcint_maskvalue;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t rx_pin_read()
|
|
||||||
{
|
|
||||||
return *_receivePortRegister & _receiveBitMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// The receive routine called by the interrupt handler
|
|
||||||
//
|
|
||||||
void softSerail_Recv()
|
|
||||||
{
|
|
||||||
#if GCC_VERSION < 40302
|
|
||||||
// Work-around for avr-gcc 4.3.0 OSX version bug
|
|
||||||
// Preserve the registers that the compiler misses
|
|
||||||
// (courtesy of Arduino forum user *etracer*)
|
|
||||||
asm volatile(
|
|
||||||
"push r18 \n\t"
|
|
||||||
"push r19 \n\t"
|
|
||||||
"push r20 \n\t"
|
|
||||||
"push r21 \n\t"
|
|
||||||
"push r22 \n\t"
|
|
||||||
"push r23 \n\t"
|
|
||||||
"push r26 \n\t"
|
|
||||||
"push r27 \n\t"
|
|
||||||
::);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t d = 0;
|
|
||||||
|
|
||||||
// If RX line is high, then we don't see any start bit
|
|
||||||
// so interrupt is probably not for us
|
|
||||||
if (!rx_pin_read()) //Start Bit
|
|
||||||
{
|
|
||||||
// Disable further interrupts during reception, this prevents
|
|
||||||
// triggering another interrupt directly after we return, which can
|
|
||||||
// cause problems at higher baudrates.
|
|
||||||
setRxIntMsk(false);
|
|
||||||
|
|
||||||
// Wait approximately 1/2 of a bit width to "center" the sample
|
|
||||||
tunedDelay(_rx_delay_centering);
|
|
||||||
|
|
||||||
// Read each of the 8 bits
|
|
||||||
for (uint8_t i=8; i > 0; --i)
|
|
||||||
{
|
|
||||||
tunedDelay(_rx_delay_intrabit);
|
|
||||||
d >>= 1;
|
|
||||||
|
|
||||||
if (rx_pin_read())
|
|
||||||
d |= 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (receivedCommandLength == 0) //check Already Command
|
|
||||||
{
|
|
||||||
//Set Received Data
|
|
||||||
swr_receive_buffer[receiveIndex++] = d;
|
|
||||||
|
|
||||||
//Finded Command
|
|
||||||
if (d == 0x73 && ffCount > 1 && receiveIndex > 6)
|
|
||||||
{
|
|
||||||
receivedCommandLength = receiveIndex;
|
|
||||||
receiveIndex = 0;
|
|
||||||
ffCount = 0;
|
|
||||||
}
|
|
||||||
else if (receiveIndex > _SS_MAX_RX_BUFF)
|
|
||||||
{
|
|
||||||
//Buffer Overflow
|
|
||||||
receiveIndex = 0;
|
|
||||||
ffCount = 0;
|
|
||||||
}
|
|
||||||
else if (d == 0xFF)
|
|
||||||
{
|
|
||||||
ffCount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ffCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip the stop bit
|
|
||||||
tunedDelay(_rx_delay_stopbit);
|
|
||||||
|
|
||||||
// Re-enable interrupts when we're sure to be inside the stop bit
|
|
||||||
setRxIntMsk(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GCC_VERSION < 40302
|
|
||||||
// Work-around for avr-gcc 4.3.0 OSX version bug
|
|
||||||
// Restore the registers that the compiler misses
|
|
||||||
asm volatile(
|
|
||||||
"pop r27 \n\t"
|
|
||||||
"pop r26 \n\t"
|
|
||||||
"pop r23 \n\t"
|
|
||||||
"pop r22 \n\t"
|
|
||||||
"pop r21 \n\t"
|
|
||||||
"pop r20 \n\t"
|
|
||||||
"pop r19 \n\t"
|
|
||||||
"pop r18 \n\t"
|
|
||||||
::);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
ISR(PCINT0_vect)
|
|
||||||
{
|
|
||||||
softSerail_Recv();
|
|
||||||
}
|
|
||||||
|
|
||||||
//================================================================
|
|
||||||
//Public Function from SoftwareSerial.c and modified and create
|
|
||||||
//================================================================
|
|
||||||
// Read data from buffer
|
|
||||||
void SWSerial_Read(uint8_t * receive_cmdBuffer)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < receivedCommandLength; i++)
|
|
||||||
receive_cmdBuffer[i] = swr_receive_buffer[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
void SWSerial_Write(uint8_t b)
|
|
||||||
{
|
|
||||||
volatile uint8_t *reg = _transmitPortRegister;
|
|
||||||
uint8_t oldSREG = SREG;
|
|
||||||
uint16_t delay = _tx_delay;
|
|
||||||
|
|
||||||
cli(); // turn off interrupts for a clean txmit
|
|
||||||
|
|
||||||
// Write the start bit
|
|
||||||
*reg &= transmit_InvMask;
|
|
||||||
|
|
||||||
tunedDelay(delay);
|
|
||||||
|
|
||||||
// Write each of the 8 bits
|
|
||||||
for (uint8_t i = 8; i > 0; --i)
|
|
||||||
{
|
|
||||||
if (b & 1) // choose bit
|
|
||||||
*reg |= transmit_RegMask; // send 1
|
|
||||||
else
|
|
||||||
*reg &= transmit_InvMask; // send 0
|
|
||||||
|
|
||||||
tunedDelay(delay);
|
|
||||||
b >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore pin to natural state
|
|
||||||
*reg |= transmit_RegMask;
|
|
||||||
|
|
||||||
SREG = oldSREG; // turn interrupts back on
|
|
||||||
tunedDelay(_tx_delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SWSerial_Print(uint8_t *b)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < PRINT_MAX_LENGTH; i++)
|
|
||||||
{
|
|
||||||
if (b[i] == 0x00)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
SWSerial_Write(b[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SWSerial_Begin(long speedBaud)
|
|
||||||
{
|
|
||||||
//INT TX_PIN
|
|
||||||
digitalWrite(TX_PIN, HIGH);
|
|
||||||
pinMode(TX_PIN, OUTPUT);
|
|
||||||
transmit_RegMask = digitalPinToBitMask(TX_PIN); //use Bit 1
|
|
||||||
transmit_InvMask = ~digitalPinToBitMask(TX_PIN); //use Bit 0
|
|
||||||
_transmitPortRegister = portOutputRegister(digitalPinToPort(TX_PIN));
|
|
||||||
|
|
||||||
//INIT RX_PIN
|
|
||||||
pinMode(RX_PIN, INPUT);
|
|
||||||
digitalWrite(RX_PIN, HIGH); // pullup for normal logic!
|
|
||||||
_receiveBitMask = digitalPinToBitMask(RX_PIN);
|
|
||||||
_receivePortRegister = portInputRegister(digitalPinToPort(RX_PIN));
|
|
||||||
|
|
||||||
//Set Values
|
|
||||||
uint16_t bit_delay = (F_CPU / speedBaud) / 4;
|
|
||||||
_tx_delay = subtract_cap(bit_delay, 15 / 4);
|
|
||||||
|
|
||||||
if (digitalPinToPCICR(RX_PIN))
|
|
||||||
{
|
|
||||||
_rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4);
|
|
||||||
_rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4);
|
|
||||||
_rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4);
|
|
||||||
*digitalPinToPCICR(RX_PIN) |= _BV(digitalPinToPCICRbit(RX_PIN));
|
|
||||||
_pcint_maskreg = digitalPinToPCMSK(RX_PIN);
|
|
||||||
_pcint_maskvalue = _BV(digitalPinToPCMSKbit(RX_PIN));
|
|
||||||
|
|
||||||
tunedDelay(_tx_delay); // if we were low this establishes the end
|
|
||||||
}
|
|
||||||
|
|
||||||
//Start Listen
|
|
||||||
setRxIntMsk(true);
|
|
||||||
}
|
|
@@ -23,16 +23,16 @@
|
|||||||
// Compile Option
|
// Compile Option
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
//Ubitx Board Version
|
//Ubitx Board Version
|
||||||
#define UBITX_BOARD_VERSION 5 //v1 ~ v4 : 4, v5: 5
|
#define UBITX_BOARD_VERSION 2 //v1 ~ v4 : 4, v5: 5
|
||||||
|
|
||||||
//Depending on the type of LCD mounted on the uBITX, uncomment one of the options below.
|
//Depending on the type of LCD mounted on the uBITX, uncomment one of the options below.
|
||||||
//You must select only one.
|
//You must select only one.
|
||||||
#define UBITX_DISPLAY_LCD1602P //LCD mounted on unmodified uBITX (Parallel)
|
//#define UBITX_DISPLAY_LCD1602P //LCD mounted on unmodified uBITX (Parallel)
|
||||||
//#define UBITX_DISPLAY_LCD1602I //I2C type 16 x 02 LCD
|
//#define UBITX_DISPLAY_LCD1602I //I2C type 16 x 02 LCD
|
||||||
//#define UBITX_DISPLAY_LCD1602I_DUAL //I2C type 16 x02 LCD Dual
|
//#define UBITX_DISPLAY_LCD1602I_DUAL //I2C type 16 x02 LCD Dual
|
||||||
//#define UBITX_DISPLAY_LCD2004P //24 x 04 LCD (Parallel)
|
//#define UBITX_DISPLAY_LCD2004P //24 x 04 LCD (Parallel)
|
||||||
//#define UBITX_DISPLAY_LCD2004I //I2C type 24 x 04 LCD
|
//#define UBITX_DISPLAY_LCD2004I //I2C type 24 x 04 LCD
|
||||||
//#define UBITX_DISPLAY_NEXTION //NEXTION LCD
|
#define UBITX_DISPLAY_NEXTION //NEXTION LCD
|
||||||
|
|
||||||
//#define UBITX_DISPLAY_NEXTION_SAFE //Only EEProm Write 770~775
|
//#define UBITX_DISPLAY_NEXTION_SAFE //Only EEProm Write 770~775
|
||||||
#define I2C_LCD_MASTER_ADDRESS_DEFAULT 0x27 //0x27 //DEFAULT, if Set I2C Address by uBITX Manager, read from EEProm
|
#define I2C_LCD_MASTER_ADDRESS_DEFAULT 0x27 //0x27 //DEFAULT, if Set I2C Address by uBITX Manager, read from EEProm
|
||||||
@@ -69,7 +69,7 @@ extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode
|
|||||||
#define FN_CW_SPEED 1 //152
|
#define FN_CW_SPEED 1 //152
|
||||||
#define FN_VFOTOMEM 1 //254
|
#define FN_VFOTOMEM 1 //254
|
||||||
#define FN_MEMTOVFO 1 //188
|
#define FN_MEMTOVFO 1 //188
|
||||||
#define FN_MEMORYKEYER 1 //156
|
#define FN_MEMORYKEYER 0 //156
|
||||||
#define FN_WSPR 1 //1044
|
#define FN_WSPR 1 //1044
|
||||||
#define FN_SDRMODE 1 //68
|
#define FN_SDRMODE 1 //68
|
||||||
#define FN_CALIBRATION 1 //666
|
#define FN_CALIBRATION 1 //666
|
||||||
|
@@ -172,15 +172,15 @@ byte isShiftDisplayCWFreq = 1; //Display Frequency
|
|||||||
int shiftDisplayAdjustVal = 0; //
|
int shiftDisplayAdjustVal = 0; //
|
||||||
|
|
||||||
//Variables for auto cw mode
|
//Variables for auto cw mode
|
||||||
byte isCWAutoMode = 0; //0 : none, 1 : CW_AutoMode_Menu_Selection, 2 : CW_AutoMode Sending
|
//byte isCWAutoMode = 0; //0 : none, 1 : CW_AutoMode_Menu_Selection, 2 : CW_AutoMode Sending
|
||||||
byte cwAutoTextCount = 0; //cwAutoText Count
|
//byte cwAutoTextCount = 0; //cwAutoText Count
|
||||||
byte beforeCWTextIndex = 255; //when auto cw start, always beforeCWTextIndex = 255, (for first time check)
|
//byte beforeCWTextIndex = 255; //when auto cw start, always beforeCWTextIndex = 255, (for first time check)
|
||||||
byte cwAutoDialType = 0; //0 : CW Text Change, 1 : Frequency Tune
|
//byte cwAutoDialType = 0; //0 : CW Text Change, 1 : Frequency Tune
|
||||||
|
|
||||||
#define AUTO_CW_RESERVE_MAX 3
|
//#define AUTO_CW_RESERVE_MAX 3
|
||||||
byte autoCWSendReserv[AUTO_CW_RESERVE_MAX]; //Reserve CW Auto Send
|
//byte autoCWSendReserv[AUTO_CW_RESERVE_MAX]; //Reserve CW Auto Send
|
||||||
byte autoCWSendReservCount = 0; //Reserve CW Text Cound
|
//byte autoCWSendReservCount = 0; //Reserve CW Text Cound
|
||||||
byte sendingCWTextIndex = 0; //cw auto seding Text Index
|
//byte sendingCWTextIndex = 0; //cw auto seding Text Index
|
||||||
|
|
||||||
byte userCallsignLength = 0; //7 : display callsign at system startup, 6~0 : callsign length (range : 1~18)
|
byte userCallsignLength = 0; //7 : display callsign at system startup, 6~0 : callsign length (range : 1~18)
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ char splitOn = 0; //working split, uses VFO B as the transmit freque
|
|||||||
char keyDown = 0; //in cw mode, denotes the carrier is being transmitted
|
char keyDown = 0; //in cw mode, denotes the carrier is being transmitted
|
||||||
|
|
||||||
char isUSB = 0; //upper sideband was selected, this is reset to the default for the
|
char isUSB = 0; //upper sideband was selected, this is reset to the default for the
|
||||||
char isTest = 0; // two-tone test mode
|
//char isTest = 0; // two-tone test mode
|
||||||
char cwMode = 0; //compatible original source, and extend mode //if cwMode == 0, mode check : isUSB, cwMode > 0, mode Check : cwMode
|
char cwMode = 0; //compatible original source, and extend mode //if cwMode == 0, mode check : isUSB, cwMode > 0, mode Check : cwMode
|
||||||
//iscwMode = 0 : ssbmode, 1 :cwl, 2 : cwu, 3 : cwn (none tx)
|
//iscwMode = 0 : ssbmode, 1 :cwl, 2 : cwu, 3 : cwn (none tx)
|
||||||
char digiMode = 0; // 0: normal uBITX behavior (transmit LSB/USB when PTT is depressed)
|
char digiMode = 0; // 0: normal uBITX behavior (transmit LSB/USB when PTT is depressed)
|
||||||
@@ -342,7 +342,7 @@ byte delay_background(unsigned delayTime, byte fromType){ //fromType : 4 autoCWK
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
//Check PTT while auto Sending
|
//Check PTT while auto Sending
|
||||||
autoSendPTTCheck();
|
//autoSendPTTCheck();
|
||||||
|
|
||||||
Check_Cat(3);
|
Check_Cat(3);
|
||||||
}
|
}
|
||||||
@@ -732,8 +732,8 @@ void checkButton(){
|
|||||||
SetSWActivePage(1);
|
SetSWActivePage(1);
|
||||||
doMenu();
|
doMenu();
|
||||||
|
|
||||||
if (isCWAutoMode == 0)
|
//if (isCWAutoMode == 0)
|
||||||
SetSWActivePage(0);
|
SetSWActivePage(0);
|
||||||
#else
|
#else
|
||||||
doMenu();
|
doMenu();
|
||||||
#endif
|
#endif
|
||||||
@@ -1453,6 +1453,8 @@ void setup()
|
|||||||
factory_alignment();
|
factory_alignment();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
iopSendMode(cwMode, isUSB, digiMode);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Auto save Frequency and Mode with Protected eeprom life by KD8CEC
|
//Auto save Frequency and Mode with Protected eeprom life by KD8CEC
|
||||||
@@ -1511,15 +1513,16 @@ void loop(){
|
|||||||
|
|
||||||
//tune only when not tranmsitting
|
//tune only when not tranmsitting
|
||||||
if (!inTx){
|
if (!inTx){
|
||||||
if (isCWAutoMode == 0 || cwAutoDialType == 1)
|
//if (isCWAutoMode == 0 || cwAutoDialType == 1)
|
||||||
{
|
//{
|
||||||
if (ritOn)
|
if (ritOn)
|
||||||
doRIT();
|
doRIT();
|
||||||
else
|
else
|
||||||
doTuningWithThresHold();
|
doTuningWithThresHold();
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (isCWAutoMode == 0 && beforeIdle_ProcessTime < millis() - 250) {
|
// KC4UPR: Updated to 100 msec (instead of 250 msec) for improved display responsiveness)
|
||||||
|
if (beforeIdle_ProcessTime < millis() - 100) {
|
||||||
idle_process();
|
idle_process();
|
||||||
checkAutoSaveFreqMode(); //move here form out scope for reduce cpu use rate
|
checkAutoSaveFreqMode(); //move here form out scope for reduce cpu use rate
|
||||||
beforeIdle_ProcessTime = millis();
|
beforeIdle_ProcessTime = millis();
|
||||||
|
@@ -417,20 +417,20 @@ void updateDisplay() {
|
|||||||
memset(c, 0, sizeof(c));
|
memset(c, 0, sizeof(c));
|
||||||
|
|
||||||
if (inTx){
|
if (inTx){
|
||||||
if (isCWAutoMode == 2) {
|
//if (isCWAutoMode == 2) {
|
||||||
for (i = 0; i < 4; i++)
|
// for (i = 0; i < 4; i++)
|
||||||
c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' ');
|
// c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' ');
|
||||||
|
|
||||||
//display Sending Index
|
//display Sending Index
|
||||||
c[4] = byteToChar(sendingCWTextIndex);
|
// c[4] = byteToChar(sendingCWTextIndex);
|
||||||
c[5] = '=';
|
// c[5] = '=';
|
||||||
}
|
//}
|
||||||
else {
|
//else {
|
||||||
if (cwTimeout > 0)
|
if (cwTimeout > 0)
|
||||||
strcpy(c, " CW:");
|
strcpy(c, " CW:");
|
||||||
else
|
else
|
||||||
strcpy(c, " TX:");
|
strcpy(c, " TX:");
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (ritOn)
|
if (ritOn)
|
||||||
@@ -439,15 +439,15 @@ void updateDisplay() {
|
|||||||
if (cwMode == 0)
|
if (cwMode == 0)
|
||||||
{
|
{
|
||||||
if (digiMode == 1) {
|
if (digiMode == 1) {
|
||||||
if (isUSB)
|
// if (isUSB)
|
||||||
strcpy(c, "DGU ");
|
strcpy(c, "DIG ");
|
||||||
else
|
// else
|
||||||
strcpy(c, "DGL ");
|
// strcpy(c, "DGL ");
|
||||||
} else if (isTest == 1) {
|
// } else if (isTest == 1) {
|
||||||
if (isUSB)
|
// if (isUSB)
|
||||||
strcpy(c, "TTU ");
|
// strcpy(c, "TTU ");
|
||||||
else
|
// else
|
||||||
strcpy(c, "TTL ");
|
// strcpy(c, "TTL ");
|
||||||
} else {
|
} else {
|
||||||
if (isUSB)
|
if (isUSB)
|
||||||
strcpy(c, "USB ");
|
strcpy(c, "USB ");
|
||||||
@@ -457,11 +457,11 @@ void updateDisplay() {
|
|||||||
}
|
}
|
||||||
else if (cwMode == 1)
|
else if (cwMode == 1)
|
||||||
{
|
{
|
||||||
strcpy(c, "CWL ");
|
strcpy(c, "CWR ");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strcpy(c, "CWU ");
|
strcpy(c, "CW ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (vfoActive == VFO_A) // VFO A is active
|
if (vfoActive == VFO_A) // VFO A is active
|
||||||
@@ -507,10 +507,10 @@ void updateDisplay() {
|
|||||||
LCD_SetCursor(5,diplayVFOLine);
|
LCD_SetCursor(5,diplayVFOLine);
|
||||||
LCD_Write((uint8_t)0);
|
LCD_Write((uint8_t)0);
|
||||||
}
|
}
|
||||||
else if (isCWAutoMode == 2){
|
//else if (isCWAutoMode == 2){
|
||||||
LCD_SetCursor(5,diplayVFOLine);
|
// LCD_SetCursor(5,diplayVFOLine);
|
||||||
LCD_Write(0x7E);
|
// LCD_Write(0x7E);
|
||||||
}
|
//}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LCD_SetCursor(5,diplayVFOLine);
|
LCD_SetCursor(5,diplayVFOLine);
|
||||||
@@ -518,8 +518,6 @@ void updateDisplay() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char line2Buffer[17];
|
char line2Buffer[17];
|
||||||
//KD8CEC 200Hz ST
|
//KD8CEC 200Hz ST
|
||||||
//L14.150 200Hz ST
|
//L14.150 200Hz ST
|
||||||
@@ -532,6 +530,15 @@ int freqScrollPosition = 0;
|
|||||||
void updateLine2Buffer(char displayType)
|
void updateLine2Buffer(char displayType)
|
||||||
{
|
{
|
||||||
unsigned long tmpFreq = 0;
|
unsigned long tmpFreq = 0;
|
||||||
|
|
||||||
|
if (stateTopLine == 2) {
|
||||||
|
strncpy(line2Buffer, iopMenuDisplay, 16);
|
||||||
|
stateTopLine = 1;
|
||||||
|
}
|
||||||
|
if (stateTopLine == 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ritOn)
|
if (ritOn)
|
||||||
{
|
{
|
||||||
strcpy(line2Buffer, "RitTX:");
|
strcpy(line2Buffer, "RitTX:");
|
||||||
@@ -679,7 +686,11 @@ void updateLine2Buffer(char displayType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
line2Buffer[13] = ' ';
|
line2Buffer[13] = ' ';
|
||||||
|
|
||||||
|
// KC4UPR: Replacing these all with IOP status
|
||||||
|
//line2Buffer[13] = iopStatusWindow[0];
|
||||||
|
//line2Buffer[14] = iopStatusWindow[1];
|
||||||
|
//line2Buffer[15] = iopStatusWindow[2];
|
||||||
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
||||||
if (sdrModeOn == 1)
|
if (sdrModeOn == 1)
|
||||||
{
|
{
|
||||||
@@ -735,7 +746,7 @@ void idle_process()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
//if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message
|
//if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message
|
||||||
if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) {
|
if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2) || stateTopLine > 0) {
|
||||||
if (checkCount++ > 1)
|
if (checkCount++ > 1)
|
||||||
{
|
{
|
||||||
updateLine2Buffer(0); //call by scheduler
|
updateLine2Buffer(0); //call by scheduler
|
||||||
@@ -745,6 +756,16 @@ void idle_process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stateTopLine > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (!displaySmeter) {
|
||||||
|
if (delaySmeter < millis()) {
|
||||||
|
displaySmeter = true;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
//S-Meter Display
|
//S-Meter Display
|
||||||
if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency))
|
if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency))
|
||||||
{
|
{
|
||||||
|
@@ -1,727 +0,0 @@
|
|||||||
/*************************************************************************
|
|
||||||
KD8CEC's uBITX Display Routine for LCD1602 Dual LCD
|
|
||||||
1.This is the display code for the 16x02 Dual LCD
|
|
||||||
2.Some functions moved from uBITX_Ui.
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
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/>.
|
|
||||||
|
|
||||||
**************************************************************************/
|
|
||||||
#include "ubitx.h"
|
|
||||||
#include "ubitx_lcd.h"
|
|
||||||
|
|
||||||
//========================================================================
|
|
||||||
//Begin of I2CTinyLCD Library for Dual LCD by KD8CEC
|
|
||||||
//========================================================================
|
|
||||||
#ifdef UBITX_DISPLAY_LCD1602I_DUAL
|
|
||||||
|
|
||||||
#include <Wire.h>
|
|
||||||
/*************************************************************************
|
|
||||||
I2C Tiny LCD Library
|
|
||||||
Referecnce Source : LiquidCrystal_I2C.cpp // Based on the work by DFRobot
|
|
||||||
KD8CEC
|
|
||||||
|
|
||||||
This source code is modified version for small program memory
|
|
||||||
from Arduino LiquidCrystal_I2C Library
|
|
||||||
|
|
||||||
I wrote this code myself, so there is no license restriction.
|
|
||||||
So this code allows anyone to write with confidence.
|
|
||||||
But keep it as long as the original author of the code.
|
|
||||||
Ian KD8CEC
|
|
||||||
**************************************************************************/
|
|
||||||
#define UBITX_DISPLAY_LCD1602_BASE
|
|
||||||
|
|
||||||
#define En B00000100 // Enable bit
|
|
||||||
#define Rw B00000010 // Read/Write bit
|
|
||||||
#define Rs B00000001 // Register select bit
|
|
||||||
|
|
||||||
#define LCD_Command(x) (LCD_Send(x, 0))
|
|
||||||
#define LCD_Write(x) (LCD_Send(x, Rs))
|
|
||||||
|
|
||||||
uint8_t _Addr;
|
|
||||||
uint8_t _displayfunction;
|
|
||||||
uint8_t _displaycontrol;
|
|
||||||
uint8_t _displaymode;
|
|
||||||
uint8_t _numlines;
|
|
||||||
uint8_t _cols;
|
|
||||||
uint8_t _rows;
|
|
||||||
uint8_t _backlightval;
|
|
||||||
|
|
||||||
#define printIIC(args) Wire.write(args)
|
|
||||||
|
|
||||||
void expanderWrite(uint8_t _data)
|
|
||||||
{
|
|
||||||
Wire.beginTransmission(_Addr);
|
|
||||||
printIIC((int)(_data) | _backlightval);
|
|
||||||
Wire.endTransmission();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulseEnable(uint8_t _data){
|
|
||||||
expanderWrite(_data | En); // En high
|
|
||||||
delayMicroseconds(1); // enable pulse must be >450ns
|
|
||||||
|
|
||||||
expanderWrite(_data & ~En); // En low
|
|
||||||
delayMicroseconds(50); // commands need > 37us to settle
|
|
||||||
}
|
|
||||||
|
|
||||||
void write4bits(uint8_t value)
|
|
||||||
{
|
|
||||||
expanderWrite(value);
|
|
||||||
pulseEnable(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LCD_Send(uint8_t value, uint8_t mode)
|
|
||||||
{
|
|
||||||
uint8_t highnib=value&0xf0;
|
|
||||||
uint8_t lownib=(value<<4)&0xf0;
|
|
||||||
write4bits((highnib)|mode);
|
|
||||||
write4bits((lownib)|mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Turn the (optional) backlight off/on
|
|
||||||
void noBacklight(void) {
|
|
||||||
_backlightval=LCD_NOBACKLIGHT;
|
|
||||||
expanderWrite(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void backlight(void) {
|
|
||||||
_backlightval=LCD_BACKLIGHT;
|
|
||||||
expanderWrite(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LCD1602_Dual_Init()
|
|
||||||
{
|
|
||||||
//I2C Init
|
|
||||||
_cols = 16;
|
|
||||||
_rows = 2;
|
|
||||||
_backlightval = LCD_NOBACKLIGHT;
|
|
||||||
Wire.begin();
|
|
||||||
|
|
||||||
delay(50);
|
|
||||||
|
|
||||||
// Now we pull both RS and R/W low to begin commands
|
|
||||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
|
||||||
expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
|
|
||||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
|
||||||
expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
|
|
||||||
delay(1000);
|
|
||||||
//put the LCD into 4 bit mode
|
|
||||||
// this is according to the hitachi HD44780 datasheet
|
|
||||||
// figure 24, pg 46
|
|
||||||
|
|
||||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
|
||||||
// we start in 8bit mode, try to set 4 bit mode
|
|
||||||
write4bits(0x03 << 4);
|
|
||||||
delayMicroseconds(4500); // wait min 4.1ms
|
|
||||||
|
|
||||||
// second try
|
|
||||||
write4bits(0x03 << 4);
|
|
||||||
delayMicroseconds(4500); // wait min 4.1ms
|
|
||||||
|
|
||||||
// third go!
|
|
||||||
write4bits(0x03 << 4);
|
|
||||||
delayMicroseconds(150);
|
|
||||||
|
|
||||||
// finally, set to 4-bit interface
|
|
||||||
write4bits(0x02 << 4);
|
|
||||||
|
|
||||||
// finally, set # lines, font size, etc.
|
|
||||||
LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE);
|
|
||||||
|
|
||||||
// turn the display on with no cursor or blinking default
|
|
||||||
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
|
|
||||||
|
|
||||||
// clear it off
|
|
||||||
LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
|
||||||
//delayMicroseconds(2000); // this command takes a long time!
|
|
||||||
delayMicroseconds(1000); // this command takes a long time!
|
|
||||||
|
|
||||||
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
|
|
||||||
|
|
||||||
backlight();
|
|
||||||
|
|
||||||
|
|
||||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
|
||||||
// we start in 8bit mode, try to set 4 bit mode
|
|
||||||
write4bits(0x03 << 4);
|
|
||||||
delayMicroseconds(4500); // wait min 4.1ms
|
|
||||||
|
|
||||||
// second try
|
|
||||||
write4bits(0x03 << 4);
|
|
||||||
delayMicroseconds(4500); // wait min 4.1ms
|
|
||||||
|
|
||||||
// third go!
|
|
||||||
write4bits(0x03 << 4);
|
|
||||||
delayMicroseconds(150);
|
|
||||||
|
|
||||||
// finally, set to 4-bit interface
|
|
||||||
write4bits(0x02 << 4);
|
|
||||||
|
|
||||||
// finally, set # lines, font size, etc.
|
|
||||||
LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE);
|
|
||||||
|
|
||||||
// turn the display on with no cursor or blinking default
|
|
||||||
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
|
|
||||||
|
|
||||||
// clear it off
|
|
||||||
LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
|
||||||
//delayMicroseconds(2000); // this command takes a long time!
|
|
||||||
delayMicroseconds(1000); // this command takes a long time!
|
|
||||||
|
|
||||||
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
|
|
||||||
|
|
||||||
backlight();
|
|
||||||
|
|
||||||
//Change to Default LCD (Master)
|
|
||||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
|
||||||
// 16 X 02 LCD Routines
|
|
||||||
//Begin of Display Base Routines (Init, printLine..)
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
void LCD_Print(const char *c)
|
|
||||||
{
|
|
||||||
for (uint8_t i = 0; i < strlen(c); i++)
|
|
||||||
{
|
|
||||||
if (*(c + i) == 0x00) return;
|
|
||||||
LCD_Write(*(c + i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
|
|
||||||
void LCD_SetCursor(uint8_t col, uint8_t row)
|
|
||||||
{
|
|
||||||
LCD_Command(LCD_SETDDRAMADDR | (col + row_offsets[row])); //0 : 0x00, 1 : 0x40, only for 20 x 4 lcd
|
|
||||||
}
|
|
||||||
|
|
||||||
void LCD_CreateChar(uint8_t location, uint8_t charmap[])
|
|
||||||
{
|
|
||||||
location &= 0x7; // we only have 8 locations 0-7
|
|
||||||
LCD_Command(LCD_SETCGRAMADDR | (location << 3));
|
|
||||||
for (int i=0; i<8; i++)
|
|
||||||
LCD_Write(charmap[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA
|
|
||||||
//#define OPTION_SKINNYBARS
|
|
||||||
|
|
||||||
char c[30], b[30];
|
|
||||||
char printBuff[4][20]; //mirrors what is showing on the two lines of the display
|
|
||||||
|
|
||||||
void LCD_Init(void)
|
|
||||||
{
|
|
||||||
LCD1602_Dual_Init();
|
|
||||||
|
|
||||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
|
||||||
initMeter(); //for Meter Display //when dual LCD, S.Meter on second LCD
|
|
||||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// The generic routine to display one line on the LCD
|
|
||||||
void printLine(unsigned char linenmbr, const char *c) {
|
|
||||||
if ((displayOption1 & 0x01) == 0x01)
|
|
||||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
|
||||||
if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change
|
|
||||||
LCD_SetCursor(0, linenmbr); // place the cursor at the beginning of the selected line
|
|
||||||
LCD_Print(c);
|
|
||||||
strcpy(printBuff[linenmbr], c);
|
|
||||||
|
|
||||||
for (byte i = strlen(c); i < 20; i++) { // add white spaces until the end of the 20 characters line is reached
|
|
||||||
LCD_Write(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printLineF(char linenmbr, const __FlashStringHelper *c)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char tmpBuff[21];
|
|
||||||
PGM_P p = reinterpret_cast<PGM_P>(c);
|
|
||||||
|
|
||||||
for (i = 0; i < 21; i++){
|
|
||||||
unsigned char fChar = pgm_read_byte(p++);
|
|
||||||
tmpBuff[i] = fChar;
|
|
||||||
if (fChar == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
printLine(linenmbr, tmpBuff);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LCD_MAX_COLUMN 20
|
|
||||||
void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) {
|
|
||||||
if ((displayOption1 & 0x01) == 0x01)
|
|
||||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
|
||||||
|
|
||||||
LCD_SetCursor(lcdColumn, linenmbr);
|
|
||||||
|
|
||||||
for (byte i = eepromStartIndex; i <= eepromEndIndex; i++)
|
|
||||||
{
|
|
||||||
if (++lcdColumn <= LCD_MAX_COLUMN)
|
|
||||||
LCD_Write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i));
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (byte i = lcdColumn; i < 20; i++) //Right Padding by Space
|
|
||||||
LCD_Write(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
// short cut to print to the first line
|
|
||||||
void printLine1(const char *c)
|
|
||||||
{
|
|
||||||
printLine(1,c);
|
|
||||||
}
|
|
||||||
// short cut to print to the first line
|
|
||||||
void printLine2(const char *c)
|
|
||||||
{
|
|
||||||
printLine(0,c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearLine2()
|
|
||||||
{
|
|
||||||
printLine2("");
|
|
||||||
line2DisplayStatus = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// short cut to print to the first line
|
|
||||||
void printLine1Clear(){
|
|
||||||
printLine(1,"");
|
|
||||||
}
|
|
||||||
// short cut to print to the first line
|
|
||||||
void printLine2Clear(){
|
|
||||||
printLine(0, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printLine2ClearAndUpdate(){
|
|
||||||
printLine(0, "");
|
|
||||||
line2DisplayStatus = 0;
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
//==================================================================================
|
|
||||||
//End of Display Base Routines
|
|
||||||
//==================================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//==================================================================================
|
|
||||||
//Begin of User Interface Routines
|
|
||||||
//==================================================================================
|
|
||||||
|
|
||||||
//Main Display
|
|
||||||
// this builds up the top line of the display with frequency and mode
|
|
||||||
void updateDisplay() {
|
|
||||||
// tks Jack Purdum W8TEE
|
|
||||||
// replaced fsprint commmands by str commands for code size reduction
|
|
||||||
// replace code for Frequency numbering error (alignment, point...) by KD8CEC
|
|
||||||
// i also Very TNX Purdum for good source code
|
|
||||||
int i;
|
|
||||||
unsigned long tmpFreq = frequency; //
|
|
||||||
|
|
||||||
memset(c, 0, sizeof(c));
|
|
||||||
|
|
||||||
if (inTx){
|
|
||||||
if (isCWAutoMode == 2) {
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' ');
|
|
||||||
|
|
||||||
//display Sending Index
|
|
||||||
c[4] = byteToChar(sendingCWTextIndex);
|
|
||||||
c[5] = '=';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (cwTimeout > 0)
|
|
||||||
strcpy(c, " CW:");
|
|
||||||
else
|
|
||||||
strcpy(c, " TX:");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (ritOn)
|
|
||||||
strcpy(c, "RIT ");
|
|
||||||
else {
|
|
||||||
if (cwMode == 0)
|
|
||||||
{
|
|
||||||
if (isUSB)
|
|
||||||
strcpy(c, "USB ");
|
|
||||||
else
|
|
||||||
strcpy(c, "LSB ");
|
|
||||||
}
|
|
||||||
else if (cwMode == 1)
|
|
||||||
{
|
|
||||||
strcpy(c, "CWL ");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strcpy(c, "CWU ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vfoActive == VFO_A) // VFO A is active
|
|
||||||
strcat(c, "A:");
|
|
||||||
else
|
|
||||||
strcat(c, "B:");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Fixed by Mitani Massaru (JE4SMQ)
|
|
||||||
if (isShiftDisplayCWFreq == 1)
|
|
||||||
{
|
|
||||||
if (cwMode == 1) //CWL
|
|
||||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
|
||||||
else if (cwMode == 2) //CWU
|
|
||||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
//display frequency
|
|
||||||
for (int i = 15; i >= 6; i--) {
|
|
||||||
if (tmpFreq > 0) {
|
|
||||||
if (i == 12 || i == 8) c[i] = '.';
|
|
||||||
else {
|
|
||||||
c[i] = tmpFreq % 10 + 0x30;
|
|
||||||
tmpFreq /= 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
c[i] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
//remarked by KD8CEC
|
|
||||||
//already RX/TX status display, and over index (16 x 2 LCD)
|
|
||||||
printLine(1, c);
|
|
||||||
|
|
||||||
byte diplayVFOLine = 1;
|
|
||||||
if ((displayOption1 & 0x01) == 0x01)
|
|
||||||
diplayVFOLine = 0;
|
|
||||||
|
|
||||||
if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) ||
|
|
||||||
(vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) {
|
|
||||||
LCD_SetCursor(5,diplayVFOLine);
|
|
||||||
LCD_Write((uint8_t)0);
|
|
||||||
}
|
|
||||||
else if (isCWAutoMode == 2){
|
|
||||||
LCD_SetCursor(5,diplayVFOLine);
|
|
||||||
LCD_Write(0x7E);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LCD_SetCursor(5,diplayVFOLine);
|
|
||||||
LCD_Write(':');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char line2Buffer[20];
|
|
||||||
//KD8CEC 200Hz ST
|
|
||||||
//L14.150 200Hz ST
|
|
||||||
//U14.150 +150khz
|
|
||||||
int freqScrollPosition = 0;
|
|
||||||
|
|
||||||
//Example Line2 Optinal Display
|
|
||||||
//immediate execution, not call by scheulder
|
|
||||||
//warning : unused parameter 'displayType' <-- ignore, this is reserve
|
|
||||||
void updateLine2Buffer(char displayType)
|
|
||||||
{
|
|
||||||
unsigned long tmpFreq = 0;
|
|
||||||
if (ritOn)
|
|
||||||
{
|
|
||||||
strcpy(line2Buffer, "RitTX:");
|
|
||||||
|
|
||||||
//display frequency
|
|
||||||
tmpFreq = ritTxFrequency;
|
|
||||||
|
|
||||||
//Fixed by Mitani Massaru (JE4SMQ)
|
|
||||||
if (isShiftDisplayCWFreq == 1)
|
|
||||||
{
|
|
||||||
if (cwMode == 1) //CWL
|
|
||||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
|
||||||
else if (cwMode == 2) //CWU
|
|
||||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 15; i >= 6; i--) {
|
|
||||||
if (tmpFreq > 0) {
|
|
||||||
if (i == 12 || i == 8) line2Buffer[i] = '.';
|
|
||||||
else {
|
|
||||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
|
||||||
tmpFreq /= 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
line2Buffer[i] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
} //end of ritOn display
|
|
||||||
|
|
||||||
//other VFO display
|
|
||||||
if (vfoActive == VFO_B)
|
|
||||||
{
|
|
||||||
tmpFreq = vfoA;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tmpFreq = vfoB;
|
|
||||||
}
|
|
||||||
|
|
||||||
// EXAMPLE 1 & 2
|
|
||||||
//U14.150.100
|
|
||||||
//display frequency
|
|
||||||
for (int i = 9; i >= 0; i--) {
|
|
||||||
if (tmpFreq > 0) {
|
|
||||||
if (i == 2 || i == 6) line2Buffer[i] = '.';
|
|
||||||
else {
|
|
||||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
|
||||||
tmpFreq /= 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
line2Buffer[i] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&line2Buffer[10], ' ', 10);
|
|
||||||
|
|
||||||
if (isIFShift)
|
|
||||||
{
|
|
||||||
line2Buffer[6] = 'M';
|
|
||||||
line2Buffer[7] = ' ';
|
|
||||||
//IFShift Offset Value
|
|
||||||
line2Buffer[8] = 'I';
|
|
||||||
line2Buffer[9] = 'F';
|
|
||||||
|
|
||||||
line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0;
|
|
||||||
line2Buffer[11] = 0;
|
|
||||||
line2Buffer[12] = ' ';
|
|
||||||
|
|
||||||
//11, 12, 13, 14, 15
|
|
||||||
memset(b, 0, sizeof(b));
|
|
||||||
ltoa(ifShiftValue, b, DEC);
|
|
||||||
strncat(line2Buffer, b, 5);
|
|
||||||
|
|
||||||
for (int i = 12; i < 17; i++)
|
|
||||||
{
|
|
||||||
if (line2Buffer[i] == 0)
|
|
||||||
line2Buffer[i] = ' ';
|
|
||||||
}
|
|
||||||
} // end of display IF
|
|
||||||
else // step & Key Type display
|
|
||||||
{
|
|
||||||
//Step
|
|
||||||
long tmpStep = arTuneStep[tuneStepIndex -1];
|
|
||||||
|
|
||||||
byte isStepKhz = 0;
|
|
||||||
if (tmpStep >= 1000)
|
|
||||||
{
|
|
||||||
isStepKhz = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 13; i >= 11 - isStepKhz; i--) {
|
|
||||||
if (tmpStep > 0) {
|
|
||||||
line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30;
|
|
||||||
tmpStep /= 10;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
line2Buffer[i +isStepKhz] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isStepKhz == 0)
|
|
||||||
{
|
|
||||||
line2Buffer[14] = 'H';
|
|
||||||
line2Buffer[15] = 'z';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//line2Buffer[17] = ' ';
|
|
||||||
/* ianlee
|
|
||||||
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
|
||||||
if (cwKeyType == 0)
|
|
||||||
{
|
|
||||||
line2Buffer[18] = 'S';
|
|
||||||
line2Buffer[19] = 'T';
|
|
||||||
}
|
|
||||||
else if (cwKeyType == 1)
|
|
||||||
{
|
|
||||||
line2Buffer[18] = 'I';
|
|
||||||
line2Buffer[19] = 'A';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
line2Buffer[18] = 'I';
|
|
||||||
line2Buffer[19] = 'B';
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//meterType : 0 = S.Meter, 1 : P.Meter
|
|
||||||
void DisplayMeter(byte meterType, byte meterValue, char drawPosition)
|
|
||||||
{
|
|
||||||
if (meterType == 0 || meterType == 1 || meterType == 2)
|
|
||||||
{
|
|
||||||
drawMeter(meterValue);
|
|
||||||
|
|
||||||
LCD_SetCursor(drawPosition, 0);
|
|
||||||
LCD_Write('S');
|
|
||||||
|
|
||||||
LCD_Write(':');
|
|
||||||
for (int i = 0; i < 7; i++)
|
|
||||||
LCD_Write(lcdMeter[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char checkCount = 0;
|
|
||||||
char checkCountSMeter = 0;
|
|
||||||
|
|
||||||
char beforeKeyType = -1;
|
|
||||||
char displaySDRON = 0;
|
|
||||||
|
|
||||||
//execute interval : 0.25sec
|
|
||||||
void idle_process()
|
|
||||||
{
|
|
||||||
//space for user graphic display
|
|
||||||
if (menuOn == 0)
|
|
||||||
{
|
|
||||||
if ((displayOption1 & 0x10) == 0x10) //always empty topline
|
|
||||||
return;
|
|
||||||
|
|
||||||
//if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message
|
|
||||||
if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) {
|
|
||||||
if (checkCount++ > 1)
|
|
||||||
{
|
|
||||||
updateLine2Buffer(0); //call by scheduler
|
|
||||||
printLine2(line2Buffer);
|
|
||||||
line2DisplayStatus = 2;
|
|
||||||
checkCount = 0;
|
|
||||||
|
|
||||||
//check change CW Key Type
|
|
||||||
if (beforeKeyType != cwKeyType)
|
|
||||||
{
|
|
||||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
|
||||||
LCD_SetCursor(10, 0);
|
|
||||||
LCD_Write('K');
|
|
||||||
LCD_Write('E');
|
|
||||||
LCD_Write('Y');
|
|
||||||
LCD_Write(':');
|
|
||||||
|
|
||||||
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
|
||||||
if (cwKeyType == 0)
|
|
||||||
{
|
|
||||||
LCD_Write('S');
|
|
||||||
LCD_Write('T');
|
|
||||||
}
|
|
||||||
else if (cwKeyType == 1)
|
|
||||||
{
|
|
||||||
LCD_Write('I');
|
|
||||||
LCD_Write('A');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LCD_Write('I');
|
|
||||||
LCD_Write('B');
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeKeyType = cwKeyType;
|
|
||||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
|
||||||
} //Display Second Screen
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//EX for Meters
|
|
||||||
|
|
||||||
//S-Meter Display
|
|
||||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
|
||||||
if (sdrModeOn == 1)
|
|
||||||
{
|
|
||||||
if (displaySDRON == 0) //once display
|
|
||||||
{
|
|
||||||
displaySDRON = 1;
|
|
||||||
LCD_SetCursor(0, 0);
|
|
||||||
LCD_Write('S');
|
|
||||||
LCD_Write('D');
|
|
||||||
LCD_Write('R');
|
|
||||||
LCD_Write(' ');
|
|
||||||
LCD_Write('M');
|
|
||||||
LCD_Write('O');
|
|
||||||
LCD_Write('D');
|
|
||||||
LCD_Write('E');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (((displayOption1 & 0x08) == 0x08) && (++checkCountSMeter > 3))
|
|
||||||
{
|
|
||||||
int newSMeter;
|
|
||||||
displaySDRON = 0;
|
|
||||||
|
|
||||||
#ifdef USE_I2CSMETER
|
|
||||||
scaledSMeter = GetI2CSmeterValue(I2CMETER_CALCS);
|
|
||||||
#else
|
|
||||||
//VK2ETA S-Meter from MAX9814 TC pin / divide 4 by KD8CEC for reduce EEPromSize
|
|
||||||
newSMeter = analogRead(ANALOG_SMETER) / 4;
|
|
||||||
|
|
||||||
//Faster attack, Slower release
|
|
||||||
//currentSMeter = (newSMeter > currentSMeter ? ((currentSMeter * 3 + newSMeter * 7) + 5) / 10 : ((currentSMeter * 7 + newSMeter * 3) + 5) / 10);
|
|
||||||
//currentSMeter = (currentSMeter * 3 + newSMeter * 7) / 10; //remarked becaused of have already Latency time
|
|
||||||
currentSMeter = newSMeter;
|
|
||||||
|
|
||||||
scaledSMeter = 0;
|
|
||||||
for (byte s = 8; s >= 1; s--) {
|
|
||||||
if (currentSMeter > sMeterLevels[s]) {
|
|
||||||
scaledSMeter = s;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DisplayMeter(0, scaledSMeter, 0);
|
|
||||||
checkCountSMeter = 0;
|
|
||||||
} //end of S-Meter
|
|
||||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//AutoKey LCD Display Routine
|
|
||||||
void Display_AutoKeyTextIndex(byte textIndex)
|
|
||||||
{
|
|
||||||
byte diplayAutoCWLine = 0;
|
|
||||||
|
|
||||||
if ((displayOption1 & 0x01) == 0x01)
|
|
||||||
diplayAutoCWLine = 1;
|
|
||||||
LCD_SetCursor(0, diplayAutoCWLine);
|
|
||||||
LCD_Write(byteToChar(textIndex));
|
|
||||||
LCD_Write(':');
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisplayCallsign(byte callSignLength)
|
|
||||||
{
|
|
||||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
|
||||||
printLineFromEEPRom(1, 16 - userCallsignLength, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT)
|
|
||||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo)
|
|
||||||
{
|
|
||||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
|
||||||
printLineF(1, fwVersionInfo);
|
|
||||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,743 +0,0 @@
|
|||||||
/*************************************************************************
|
|
||||||
KD8CEC's uBITX Display Routine for LCD2004 Parrel & I2C
|
|
||||||
1.This is the display code for the 20x04 LCD
|
|
||||||
2.Some functions moved from uBITX_Ui.
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
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/>.
|
|
||||||
|
|
||||||
**************************************************************************/
|
|
||||||
#include "ubitx.h"
|
|
||||||
#include "ubitx_lcd.h"
|
|
||||||
|
|
||||||
//========================================================================
|
|
||||||
//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++)
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
//========================================================================
|
|
||||||
//End of TinyLCD Library by KD8CEC
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
|
||||||
//Begin of I2CTinyLCD Library by KD8CEC
|
|
||||||
//========================================================================
|
|
||||||
#ifdef UBITX_DISPLAY_LCD2004I
|
|
||||||
|
|
||||||
#include <Wire.h>
|
|
||||||
/*************************************************************************
|
|
||||||
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_LCD_MASTER_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)
|
|
||||||
{
|
|
||||||
for (uint8_t i = 0; i < strlen(c); i++)
|
|
||||||
{
|
|
||||||
if (*(c + i) == 0x00) return;
|
|
||||||
LCD_Write(*(c + i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
|
|
||||||
void LCD_SetCursor(uint8_t col, uint8_t row)
|
|
||||||
{
|
|
||||||
LCD_Command(LCD_SETDDRAMADDR | (col + row_offsets[row])); //0 : 0x00, 1 : 0x40, only for 20 x 4 lcd
|
|
||||||
}
|
|
||||||
|
|
||||||
void LCD_CreateChar(uint8_t location, uint8_t charmap[])
|
|
||||||
{
|
|
||||||
location &= 0x7; // we only have 8 locations 0-7
|
|
||||||
LCD_Command(LCD_SETCGRAMADDR | (location << 3));
|
|
||||||
for (int i=0; i<8; i++)
|
|
||||||
LCD_Write(charmap[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA
|
|
||||||
//#define OPTION_SKINNYBARS
|
|
||||||
|
|
||||||
char c[30], b[30];
|
|
||||||
char printBuff[4][21]; //mirrors what is showing on the two lines of the display
|
|
||||||
|
|
||||||
void LCD_Init(void)
|
|
||||||
{
|
|
||||||
LCD2004_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 < 20; i++) { // add white spaces until the end of the 20 characters line is reached
|
|
||||||
LCD_Write(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printLineF(char linenmbr, const __FlashStringHelper *c)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char tmpBuff[21];
|
|
||||||
PGM_P p = reinterpret_cast<PGM_P>(c);
|
|
||||||
|
|
||||||
for (i = 0; i < 21; i++){
|
|
||||||
unsigned char fChar = pgm_read_byte(p++);
|
|
||||||
tmpBuff[i] = fChar;
|
|
||||||
if (fChar == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
printLine(linenmbr, tmpBuff);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LCD_MAX_COLUMN 20
|
|
||||||
void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) {
|
|
||||||
if ((displayOption1 & 0x01) == 0x01)
|
|
||||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
|
||||||
|
|
||||||
LCD_SetCursor(lcdColumn, linenmbr);
|
|
||||||
|
|
||||||
for (byte i = eepromStartIndex; i <= eepromEndIndex; i++)
|
|
||||||
{
|
|
||||||
if (++lcdColumn <= LCD_MAX_COLUMN)
|
|
||||||
LCD_Write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i));
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (byte i = lcdColumn; i < 20; i++) //Right Padding by Space
|
|
||||||
LCD_Write(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
// short cut to print to the first line
|
|
||||||
void printLine1(const char *c)
|
|
||||||
{
|
|
||||||
printLine(1,c);
|
|
||||||
}
|
|
||||||
// short cut to print to the first line
|
|
||||||
void printLine2(const char *c)
|
|
||||||
{
|
|
||||||
printLine(0,c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearLine2()
|
|
||||||
{
|
|
||||||
printLine2("");
|
|
||||||
line2DisplayStatus = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// short cut to print to the first line
|
|
||||||
void printLine1Clear(){
|
|
||||||
printLine(1,"");
|
|
||||||
}
|
|
||||||
// short cut to print to the first line
|
|
||||||
void printLine2Clear(){
|
|
||||||
printLine(0, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printLine2ClearAndUpdate(){
|
|
||||||
printLine(0, "");
|
|
||||||
line2DisplayStatus = 0;
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
//==================================================================================
|
|
||||||
//End of Display Base Routines
|
|
||||||
//==================================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//==================================================================================
|
|
||||||
//Begin of User Interface Routines
|
|
||||||
//==================================================================================
|
|
||||||
|
|
||||||
//Main Display
|
|
||||||
// this builds up the top line of the display with frequency and mode
|
|
||||||
void updateDisplay() {
|
|
||||||
// tks Jack Purdum W8TEE
|
|
||||||
// replaced fsprint commmands by str commands for code size reduction
|
|
||||||
// replace code for Frequency numbering error (alignment, point...) by KD8CEC
|
|
||||||
// i also Very TNX Purdum for good source code
|
|
||||||
int i;
|
|
||||||
unsigned long tmpFreq = frequency; //
|
|
||||||
|
|
||||||
memset(c, 0, sizeof(c));
|
|
||||||
|
|
||||||
if (inTx){
|
|
||||||
if (isCWAutoMode == 2) {
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' ');
|
|
||||||
|
|
||||||
//display Sending Index
|
|
||||||
c[4] = byteToChar(sendingCWTextIndex);
|
|
||||||
c[5] = '=';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (cwTimeout > 0)
|
|
||||||
strcpy(c, " CW:");
|
|
||||||
else
|
|
||||||
strcpy(c, " TX:");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (ritOn)
|
|
||||||
strcpy(c, "RIT ");
|
|
||||||
else {
|
|
||||||
if (cwMode == 0)
|
|
||||||
{
|
|
||||||
if (isUSB)
|
|
||||||
strcpy(c, "USB ");
|
|
||||||
else
|
|
||||||
strcpy(c, "LSB ");
|
|
||||||
}
|
|
||||||
else if (cwMode == 1)
|
|
||||||
{
|
|
||||||
strcpy(c, "CWL ");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strcpy(c, "CWU ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vfoActive == VFO_A) // VFO A is active
|
|
||||||
strcat(c, "A:");
|
|
||||||
else
|
|
||||||
strcat(c, "B:");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Fixed by Mitani Massaru (JE4SMQ)
|
|
||||||
if (isShiftDisplayCWFreq == 1)
|
|
||||||
{
|
|
||||||
if (cwMode == 1) //CWL
|
|
||||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
|
||||||
else if (cwMode == 2) //CWU
|
|
||||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
//display frequency
|
|
||||||
for (int i = 15; i >= 6; i--) {
|
|
||||||
if (tmpFreq > 0) {
|
|
||||||
if (i == 12 || i == 8) c[i] = '.';
|
|
||||||
else {
|
|
||||||
c[i] = tmpFreq % 10 + 0x30;
|
|
||||||
tmpFreq /= 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
c[i] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
byte diplayVFOLine = 1;
|
|
||||||
if ((displayOption1 & 0x01) == 0x01)
|
|
||||||
diplayVFOLine = 0;
|
|
||||||
|
|
||||||
if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) ||
|
|
||||||
(vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) {
|
|
||||||
LCD_SetCursor(5,diplayVFOLine);
|
|
||||||
LCD_Write((uint8_t)0);
|
|
||||||
}
|
|
||||||
else if (isCWAutoMode == 2){
|
|
||||||
LCD_SetCursor(5,diplayVFOLine);
|
|
||||||
LCD_Write(0x7E);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LCD_SetCursor(5,diplayVFOLine);
|
|
||||||
LCD_Write(':');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char line2Buffer[20];
|
|
||||||
//KD8CEC 200Hz ST
|
|
||||||
//L14.150 200Hz ST
|
|
||||||
//U14.150 +150khz
|
|
||||||
int freqScrollPosition = 0;
|
|
||||||
|
|
||||||
//Example Line2 Optinal Display
|
|
||||||
//immediate execution, not call by scheulder
|
|
||||||
//warning : unused parameter 'displayType' <-- ignore, this is reserve
|
|
||||||
void updateLine2Buffer(char displayType)
|
|
||||||
{
|
|
||||||
unsigned long tmpFreq = 0;
|
|
||||||
if (ritOn)
|
|
||||||
{
|
|
||||||
strcpy(line2Buffer, "RitTX:");
|
|
||||||
|
|
||||||
//display frequency
|
|
||||||
tmpFreq = ritTxFrequency;
|
|
||||||
|
|
||||||
//Fixed by Mitani Massaru (JE4SMQ)
|
|
||||||
if (isShiftDisplayCWFreq == 1)
|
|
||||||
{
|
|
||||||
if (cwMode == 1) //CWL
|
|
||||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
|
||||||
else if (cwMode == 2) //CWU
|
|
||||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 15; i >= 6; i--) {
|
|
||||||
if (tmpFreq > 0) {
|
|
||||||
if (i == 12 || i == 8) line2Buffer[i] = '.';
|
|
||||||
else {
|
|
||||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
|
||||||
tmpFreq /= 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
line2Buffer[i] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
} //end of ritOn display
|
|
||||||
|
|
||||||
//other VFO display
|
|
||||||
if (vfoActive == VFO_B)
|
|
||||||
{
|
|
||||||
tmpFreq = vfoA;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tmpFreq = vfoB;
|
|
||||||
}
|
|
||||||
|
|
||||||
// EXAMPLE 1 & 2
|
|
||||||
//U14.150.100
|
|
||||||
//display frequency
|
|
||||||
for (int i = 9; i >= 0; i--) {
|
|
||||||
if (tmpFreq > 0) {
|
|
||||||
if (i == 2 || i == 6) line2Buffer[i] = '.';
|
|
||||||
else {
|
|
||||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
|
||||||
tmpFreq /= 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
line2Buffer[i] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&line2Buffer[10], ' ', 10);
|
|
||||||
|
|
||||||
if (isIFShift)
|
|
||||||
{
|
|
||||||
line2Buffer[6] = 'M';
|
|
||||||
line2Buffer[7] = ' ';
|
|
||||||
//IFShift Offset Value
|
|
||||||
line2Buffer[8] = 'I';
|
|
||||||
line2Buffer[9] = 'F';
|
|
||||||
|
|
||||||
line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0;
|
|
||||||
line2Buffer[11] = 0;
|
|
||||||
line2Buffer[12] = ' ';
|
|
||||||
|
|
||||||
//11, 12, 13, 14, 15
|
|
||||||
memset(b, 0, sizeof(b));
|
|
||||||
ltoa(ifShiftValue, b, DEC);
|
|
||||||
strncat(line2Buffer, b, 5);
|
|
||||||
|
|
||||||
for (int i = 12; i < 17; i++)
|
|
||||||
{
|
|
||||||
if (line2Buffer[i] == 0)
|
|
||||||
line2Buffer[i] = ' ';
|
|
||||||
}
|
|
||||||
} // end of display IF
|
|
||||||
else // step & Key Type display
|
|
||||||
{
|
|
||||||
//Step
|
|
||||||
long tmpStep = arTuneStep[tuneStepIndex -1];
|
|
||||||
|
|
||||||
byte isStepKhz = 0;
|
|
||||||
if (tmpStep >= 1000)
|
|
||||||
{
|
|
||||||
isStepKhz = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 14; i >= 12 - isStepKhz; i--) {
|
|
||||||
if (tmpStep > 0) {
|
|
||||||
line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30;
|
|
||||||
tmpStep /= 10;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
line2Buffer[i +isStepKhz] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isStepKhz == 0)
|
|
||||||
{
|
|
||||||
line2Buffer[15] = 'H';
|
|
||||||
line2Buffer[16] = 'z';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
line2Buffer[17] = ' ';
|
|
||||||
|
|
||||||
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
|
||||||
if (cwKeyType == 0)
|
|
||||||
{
|
|
||||||
line2Buffer[18] = 'S';
|
|
||||||
line2Buffer[19] = 'T';
|
|
||||||
}
|
|
||||||
else if (cwKeyType == 1)
|
|
||||||
{
|
|
||||||
line2Buffer[18] = 'I';
|
|
||||||
line2Buffer[19] = 'A';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
line2Buffer[18] = 'I';
|
|
||||||
line2Buffer[19] = 'B';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//meterType : 0 = S.Meter, 1 : P.Meter
|
|
||||||
void DisplayMeter(byte meterType, byte meterValue, char drawPosition)
|
|
||||||
{
|
|
||||||
if (meterType == 0 || meterType == 1 || meterType == 2)
|
|
||||||
{
|
|
||||||
drawMeter(meterValue);
|
|
||||||
|
|
||||||
LCD_SetCursor(drawPosition, 2);
|
|
||||||
LCD_Write('S');
|
|
||||||
LCD_Write(':');
|
|
||||||
for (int i = 0; i < 7; i++) //meter 5 + +db 1 = 6
|
|
||||||
LCD_Write(lcdMeter[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char checkCount = 0;
|
|
||||||
char checkCountSMeter = 0;
|
|
||||||
|
|
||||||
//execute interval : 0.25sec
|
|
||||||
void idle_process()
|
|
||||||
{
|
|
||||||
//space for user graphic display
|
|
||||||
if (menuOn == 0)
|
|
||||||
{
|
|
||||||
if ((displayOption1 & 0x10) == 0x10) //always empty topline
|
|
||||||
return;
|
|
||||||
|
|
||||||
//if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message
|
|
||||||
if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) {
|
|
||||||
if (checkCount++ > 1)
|
|
||||||
{
|
|
||||||
updateLine2Buffer(0); //call by scheduler
|
|
||||||
printLine2(line2Buffer);
|
|
||||||
line2DisplayStatus = 2;
|
|
||||||
checkCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//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)) && (++checkCountSMeter > SMeterLatency))
|
|
||||||
{
|
|
||||||
int newSMeter;
|
|
||||||
|
|
||||||
#ifdef USE_I2CSMETER
|
|
||||||
scaledSMeter = GetI2CSmeterValue(I2CMETER_CALCS);
|
|
||||||
#else
|
|
||||||
//VK2ETA S-Meter from MAX9814 TC pin
|
|
||||||
newSMeter = analogRead(ANALOG_SMETER) / 4;
|
|
||||||
|
|
||||||
//Faster attack, Slower release
|
|
||||||
//currentSMeter = (newSMeter > currentSMeter ? ((currentSMeter * 3 + newSMeter * 7) + 5) / 10 : ((currentSMeter * 7 + newSMeter * 3) + 5) / 10);
|
|
||||||
//currentSMeter = ((currentSMeter * 7 + newSMeter * 3) + 5) / 10;
|
|
||||||
currentSMeter = newSMeter;
|
|
||||||
|
|
||||||
scaledSMeter = 0;
|
|
||||||
for (byte s = 8; s >= 1; s--) {
|
|
||||||
if (currentSMeter > sMeterLevels[s]) {
|
|
||||||
scaledSMeter = s;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DisplayMeter(0, scaledSMeter, 0);
|
|
||||||
checkCountSMeter = 0; //Reset Latency time
|
|
||||||
} //end of S-Meter
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//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, 20 - userCallsignLength, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT)
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo)
|
|
||||||
{
|
|
||||||
printLineF(3, fwVersionInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
@@ -127,13 +127,17 @@ void menuBand(int btn){
|
|||||||
|
|
||||||
//Convert Mode, Number by KD8CEC
|
//Convert Mode, Number by KD8CEC
|
||||||
//0: default, 1:not use, 2:LSB, 3:USB, 4:CWL, 5:CWU, 6:FM
|
//0: default, 1:not use, 2:LSB, 3:USB, 4:CWL, 5:CWU, 6:FM
|
||||||
byte modeToByte(){
|
// Updated: KC4UPR - 6: DIG
|
||||||
|
byte modeToByte() {
|
||||||
if (cwMode == 0)
|
if (cwMode == 0)
|
||||||
{
|
{
|
||||||
|
if (digiMode > 0) {
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
if (isUSB)
|
if (isUSB)
|
||||||
return 3 + (digiMode > 0 ? 3 + digiMode : 0);
|
return 3;
|
||||||
else
|
else
|
||||||
return 2 + (digiMode > 0 ? 3 + digiMode : 0);
|
return 2;
|
||||||
}
|
}
|
||||||
else if (cwMode == 1)
|
else if (cwMode == 1)
|
||||||
{
|
{
|
||||||
@@ -149,7 +153,7 @@ byte modeToByte(){
|
|||||||
//autoSetModebyFreq : 0
|
//autoSetModebyFreq : 0
|
||||||
//autoSetModebyFreq : 1, if (modValue is not set, set mode by frequency)
|
//autoSetModebyFreq : 1, if (modValue is not set, set mode by frequency)
|
||||||
void byteToMode(byte modeValue, byte autoSetModebyFreq){
|
void byteToMode(byte modeValue, byte autoSetModebyFreq){
|
||||||
isTest = false; // test never settable from EEPROM
|
//isTest = false; // test never settable from EEPROM
|
||||||
isUSB = false;
|
isUSB = false;
|
||||||
cwMode = 0;
|
cwMode = 0;
|
||||||
digiMode = 0;
|
digiMode = 0;
|
||||||
@@ -174,23 +178,10 @@ void byteToMode(byte modeValue, byte autoSetModebyFreq){
|
|||||||
cwMode = 2;
|
cwMode = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: // DGL
|
case 6: // DIG
|
||||||
digiMode = 1;
|
digiMode = 1;
|
||||||
break;
|
|
||||||
|
|
||||||
case 7: // DGU
|
|
||||||
isUSB = true;
|
|
||||||
digiMode = 1;
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
case 8: // TTL
|
|
||||||
isUSB = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 9: // TTU
|
|
||||||
isUSB = true;
|
isUSB = true;
|
||||||
break;
|
break;
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* if (modeValue == 4) {
|
/* if (modeValue == 4) {
|
||||||
@@ -548,6 +539,7 @@ void displayEmptyData(void){
|
|||||||
delay_background(2000, 0);
|
delay_background(2000, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
//Builtin CW Keyer Logic by KD8CEC
|
//Builtin CW Keyer Logic by KD8CEC
|
||||||
void menuCWAutoKey(int btn){
|
void menuCWAutoKey(int btn){
|
||||||
if (!btn){
|
if (!btn){
|
||||||
@@ -570,6 +562,7 @@ void menuCWAutoKey(int btn){
|
|||||||
updateDisplay();
|
updateDisplay();
|
||||||
menuOn = 0;
|
menuOn = 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//Standalone WSPR Beacone
|
//Standalone WSPR Beacone
|
||||||
void menuWSPRSend(int btn){
|
void menuWSPRSend(int btn){
|
||||||
@@ -992,16 +985,13 @@ void menuSelectMode(int btn){
|
|||||||
}
|
}
|
||||||
// modify if digital mode is set
|
// modify if digital mode is set
|
||||||
if (digiMode > 0) {
|
if (digiMode > 0) {
|
||||||
selectModeType += (3 + digiMode);
|
|
||||||
|
selectModeType = 4;
|
||||||
// modify if two-tone test mode is set
|
|
||||||
} else if (isTest > 0) {
|
|
||||||
selectModeType += 5;
|
|
||||||
}
|
}
|
||||||
} else if (cwMode == 1) {
|
} else if (cwMode == 2) {
|
||||||
selectModeType = 2; // CWL
|
selectModeType = 2; // CW
|
||||||
} else {
|
} else {
|
||||||
selectModeType = 3; // CWU
|
selectModeType = 3; // CWR
|
||||||
}
|
}
|
||||||
/*if (cwMode == 0 && isUSB == 0)
|
/*if (cwMode == 0 && isUSB == 0)
|
||||||
selectModeType = 0;
|
selectModeType = 0;
|
||||||
@@ -1013,30 +1003,30 @@ void menuSelectMode(int btn){
|
|||||||
selectModeType = 3;*/
|
selectModeType = 3;*/
|
||||||
|
|
||||||
beforeMode = selectModeType;
|
beforeMode = selectModeType;
|
||||||
selectModeType = getValueByKnob(11, selectModeType, 0, 7, 1, " LSB USB CWL CWU DGL DGU TTL TTU", 4); //3 : Select Mode, targetValue, minKnobValue, maxKnobValue, stepSize
|
selectModeType = getValueByKnob(11, selectModeType, 0, 4, 1, " LSB USB CW CWR DIG", 4); //3 : Select Mode, targetValue, minKnobValue, maxKnobValue, stepSize
|
||||||
|
|
||||||
if (beforeMode != selectModeType)
|
if (beforeMode != selectModeType)
|
||||||
{
|
{
|
||||||
//printLineF1(F("Changed Mode"));
|
//printLineF1(F("Changed Mode"));
|
||||||
if (selectModeType == 0) {
|
if (selectModeType == 0) {
|
||||||
cwMode = 0; isUSB = 0; digiMode = 0; isTest = 0;
|
cwMode = 0; isUSB = 0; digiMode = 0; //isTest = 0;
|
||||||
} else if (selectModeType == 1) {
|
} else if (selectModeType == 1) {
|
||||||
cwMode = 0; isUSB = 1; digiMode = 0; isTest = 0;
|
cwMode = 0; isUSB = 1; digiMode = 0; //isTest = 0;
|
||||||
} else if (selectModeType == 2) {
|
} else if (selectModeType == 2) {
|
||||||
cwMode = 1; digiMode = 0; isTest = 0;
|
cwMode = 2; digiMode = 0; //isTest = 0;
|
||||||
} else if (selectModeType == 3) {
|
} else if (selectModeType == 3) {
|
||||||
cwMode = 2; digiMode = 0; isTest = 0;
|
cwMode = 1; digiMode = 0; //isTest = 0;
|
||||||
} else if (selectModeType == 4) {
|
} else if (selectModeType == 4) {
|
||||||
cwMode = 0; isUSB = 0; digiMode = 1; isTest = 0;
|
cwMode = 0; isUSB = 1; digiMode = 1; //isTest = 0;
|
||||||
} else if (selectModeType == 5) {
|
// } else if (selectModeType == 5) {
|
||||||
cwMode = 0; isUSB = 1; digiMode = 1; isTest = 0;
|
// cwMode = 0; isUSB = 1; digiMode = 1; isTest = 0;
|
||||||
} else if (selectModeType == 6) {
|
// } else if (selectModeType == 6) {
|
||||||
cwMode = 0; isUSB = 0; digiMode = 0; isTest = 1;
|
// cwMode = 0; isUSB = 0; digiMode = 0; isTest = 1;
|
||||||
} else if (selectModeType == 7) {
|
// } else if (selectModeType == 7) {
|
||||||
cwMode = 0; isUSB = 1; digiMode = 0; isTest = 1;
|
// cwMode = 0; isUSB = 1; digiMode = 0; isTest = 1;
|
||||||
}
|
}
|
||||||
// KC4UPR: sending mode to IOP
|
// KC4UPR: sending mode to IOP
|
||||||
iopSendMode(cwMode, isUSB, digiMode, isTest);
|
iopSendMode(cwMode, isUSB, digiMode);
|
||||||
|
|
||||||
FrequencyToVFO(1);
|
FrequencyToVFO(1);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user