Compare commits
98 Commits
version0.3
...
v1.07
Author | SHA1 | Date | |
---|---|---|---|
|
0996870154 | ||
|
689cfda09e | ||
|
23f1b7cd5c | ||
|
d4ed0589e5 | ||
|
5f906a4497 | ||
|
1210f56cd1 | ||
|
e8d6792073 | ||
|
9c4b694ce2 | ||
|
02f22d66e5 | ||
|
11e47fdccc | ||
|
7aafed9e95 | ||
|
5afcdf2583 | ||
|
075f585a1e | ||
|
d0c04df9d8 | ||
|
dd6d4555a8 | ||
|
8f8850f4da | ||
|
4e9437a735 | ||
|
bad62ef728 | ||
|
384c3c41b2 | ||
|
93727e6b22 | ||
|
31a7f79569 | ||
|
d7858e35c3 | ||
|
ecd104b686 | ||
|
bd52de59d2 | ||
|
f0409d641d | ||
|
8326b1ade3 | ||
|
94a3e5ca1b | ||
|
a26978f573 | ||
|
a21dbe2fa5 | ||
|
9faa8bb44c | ||
|
d926b15e3d | ||
|
fb2c9d2cc3 | ||
|
bf68dd6c26 | ||
|
4a6909f361 | ||
|
c911d26163 | ||
|
98e3b41f5a | ||
|
e0f9148972 | ||
|
277666f82f | ||
|
e532dccce7 | ||
|
81333e7af4 | ||
|
04949cdb93 | ||
|
bbdd0947d3 | ||
|
ed767f2e34 | ||
|
a374297d49 | ||
|
1e9576ddc2 | ||
|
a7684284d2 | ||
|
c1d81d9d5b | ||
|
3b4aaa664c | ||
|
d69588d999 | ||
|
14888bb7d7 | ||
|
57cd385b8a | ||
|
e915c21412 | ||
|
60777178a8 | ||
|
dd68b38454 | ||
|
d229a10092 | ||
|
3d019cdd44 | ||
|
55cfeeb924 | ||
|
c8879e0e59 | ||
|
4f5ac283b7 | ||
|
4745790dfa | ||
|
85832de034 | ||
|
4830db78cb | ||
|
5eca64d2a9 | ||
|
3058d52551 | ||
|
04699ba074 | ||
|
aa61281c38 | ||
|
261215b1ad | ||
|
1a2f5b4fde | ||
|
8203427808 | ||
|
4e15f2150c | ||
|
82a5fd7df9 | ||
|
386a0b2d46 | ||
|
c6401af7d1 | ||
|
b153a305d6 | ||
|
e61e45d3dd | ||
|
a1f941f965 | ||
|
d1e72b3bd5 | ||
|
032e7f919f | ||
|
b6bc264332 | ||
|
b1cc5eb98a | ||
|
2fe1662d67 | ||
|
ebbc5aae5e | ||
|
209cd3a49c | ||
|
95e5c1dfe5 | ||
|
45a8479061 | ||
|
a6ad381c24 | ||
|
bcf80f851d | ||
|
16304efacd | ||
|
968024ab73 | ||
|
3e60728727 | ||
|
9781ef086b | ||
|
f27f504ea4 | ||
|
2b08a76fbf | ||
|
90655e03b8 | ||
|
8551ff1b68 | ||
|
5ce94e8e49 | ||
|
7ef9c29fa8 | ||
|
fda398046e |
119
README.md
119
README.md
@@ -1,28 +1,18 @@
|
||||
#IMPORTANT INFORMATION
|
||||
----------------------------------------------------------------------------
|
||||
- Beta 0.26 and Beta 0.261, Beta 0.262, Beta 0.27 is complete test
|
||||
- You can download and use it.
|
||||
- Now Release Version 1.061 on my blog (http://www.hamskey.com)
|
||||
- You can download and compiled hex file and uBITX Manager application on my blog (http://www.hamskey.com)
|
||||
|
||||
#NOTICE
|
||||
----------------------------------------------------------------------------
|
||||
I received uBITX a month ago and found that many features are required, and began coding with the idea of implementing minimal functionality as a general hf transceiver rather than an experimental device.
|
||||
|
||||
- fixed bugs...
|
||||
- Diallock for uBITX's sensitive encoders
|
||||
- built in softare Memory keyer and cw options control for CW communication
|
||||
- Implementation of CAT communication protocol for Digital Communication (as FT8, JT65, etc)
|
||||
- Delay Options for external Linear.
|
||||
- and more...
|
||||
|
||||
Most of the basic functions of the HF transceiver I thought were implemented.
|
||||
The minimum basic specification for uBITX to operate as a radio, I think it is finished.
|
||||
So I will release the 0.27 version and if I do not see the bug anymore, I will try to change the version name to 1.0.
|
||||
Now uBITX is an HF radio and will be able to join you in your happy hams life.
|
||||
Based on this source, you can use it by adding functions.
|
||||
|
||||
I am going to do a new project based on this source, linking with WSPR, WSJT-X and so on.
|
||||
Of course, this repository is still running. If you have any bugs or ideas, please feel free to email me.
|
||||
|
||||
http://www.hamskey.com
|
||||
|
||||
DE KD8CEC
|
||||
@@ -36,16 +26,105 @@ The copyright information of the original is below.
|
||||
KD8CEC
|
||||
----------------------------------------------------------------------------
|
||||
Prepared or finished tasks for the next version
|
||||
- Most of them are implemented and included in version 0.27.
|
||||
- User Interface on LCD -> Option by user (not need)
|
||||
- Include WSPR Beacone function - (implement other new repository)
|
||||
complete experiment
|
||||
need solve : Big code size (over 100%, then remove some functions for experment)
|
||||
need replace Si5351 Library (increase risk and need more beta tester)
|
||||
W3PM sent me his wonderful source - using BITX, GPS
|
||||
|
||||
- Reduce Program size
|
||||
- uBITX with RTL-SDR
|
||||
- Direct control for Student
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
## REVISION RECORD
|
||||
1.07 (Working...)
|
||||
- Please do not download it yet. The code will continue to change for the time being.
|
||||
- BetaVersion for Reduce program size
|
||||
|
||||
1.061
|
||||
- Added WSPR
|
||||
You only need uBITX to use WSPR. No external devices are required.
|
||||
Added Si5351 module for WSPR
|
||||
- Update uBITX Manager to Version 1.0
|
||||
- Reduce program size
|
||||
for WSPR
|
||||
for other Module
|
||||
- Fixed IF Shift Bug
|
||||
Disable IF Shift on TX
|
||||
IF shift available in USB mode
|
||||
Fixed cat routine in IF Shift setup
|
||||
- Bugs fixed
|
||||
cw start delay option
|
||||
Auto key Bug
|
||||
(found bug : LZ1LDO)
|
||||
Message selection when Auto Key is used in RIT mode
|
||||
(found bug : gerald)
|
||||
- Improve CW Keying (start TX)
|
||||
|
||||
1.05
|
||||
- include 1.05W, 1.051, 1.051W
|
||||
- for WSPR Beta Test Version
|
||||
|
||||
1.04
|
||||
- Optimized from Version1.03
|
||||
- Reduce program size (97% -> 95%)
|
||||
|
||||
1.03
|
||||
- Change eBFO Calibration Step (50 to 5)
|
||||
- Change CW Frequency Display type
|
||||
|
||||
1.02
|
||||
- Applied CW Start Delay to New CW Key logic (This is my mistake when applying the new CW Key Logic.Since uBITX operations are not significantly affected, this does not create a separate Release, It will be reflected in the next release.) - complete
|
||||
- Modified CW Key Logic for Auto Key, (available AutoKey function by any cw keytype) - complete
|
||||
- reduce cpu use usage (working)
|
||||
- reduce (working)
|
||||
|
||||
1.01
|
||||
- Fixed Cat problem with (IAMBIC A or B Selected)
|
||||
1.0
|
||||
- rename 0.30 to 1.0
|
||||
|
||||
0.35
|
||||
- vfo to channel bug fixed (not saved mode -> fixed, channel has frequency and mode)
|
||||
- add Channel tag (ch.1 ~ 10) by uBITX Manager
|
||||
- add VFO to Channel, Channel To VFO
|
||||
|
||||
0.34
|
||||
- TX Status check in auto Keysend logic
|
||||
- optimize codes
|
||||
- change default tune step size, and fixed bug
|
||||
- change IF shift step (1Hz -> 50Hz)
|
||||
|
||||
0.33
|
||||
- Added CWL, CWU Mode, (dont complete test yet)
|
||||
- fixed VFO changed bug.
|
||||
- Added Additional BFO for CWL, CWL
|
||||
- Added IF Shift
|
||||
- Change confirmation key PTT -> function key (not critical menus)
|
||||
- Change CW Key Select type, (toggle -> select by dial)
|
||||
|
||||
0.32
|
||||
- Added function Scroll Frequencty on upper line
|
||||
- Added Example code for Draw meter and remarked (you can see and use this code in source codes)
|
||||
- Added Split function, just toggle VFOs when TX/RX
|
||||
|
||||
0.31
|
||||
- Fixed CW ADC Range error
|
||||
- Display Message on Upper Line (anothor VFO Frequency, Tune Step, Selected Key Type)
|
||||
|
||||
0.30
|
||||
- implemented the function to monitor the value of all analog inputs. This allows you to monitor the status of the CW keys connected to your uBITX.
|
||||
- possible to set the ADC range for CW Keying. If no setting is made, it will have the same range as the original code. If you set the CW Keying ADC Values using uBITX Manager 0.3, you can reduce the key error.
|
||||
- Added the function to select Straight Key, IAMBICA, IAMBICB key from the menu.
|
||||
- default Band select is Ham Band mode, if you want common type, long press function key at band select menu, uBITX Manager can be used to modify frequencies to suit your country.
|
||||
|
||||
0.29
|
||||
- Remove the use of initialization values in BFO settings - using crruent value, if factory reset
|
||||
- Select Tune Step, default 0, 20, 50, 100, 200, Use the uBITX Manager to set the steps value you want. You can select Step by pressing and holding the Function Key (1sec ~ 2sec).
|
||||
- Modify Dial Lock Function, Press the Function key for more than 3 seconds to toggle dial lock.
|
||||
- created a new frequency tune method. remove original source codes, Threshold has been applied to reduce malfunction. checked the continuity of the user operating to make natural tune possible.
|
||||
- stabilize and remove many warning messages - by Pullrequest and merge
|
||||
- Changed cw keying method. removed the original code and applied Ron's code and Improved compatibility with original hardware and CAT commnication. It can be used without modification of hardware.
|
||||
|
||||
0.28
|
||||
- Fixed CAT problem with hamlib on Linux
|
||||
- restore Protocol autorecovery logic
|
||||
|
||||
0.27
|
||||
(First alpha test version, This will be renamed to the major version 1.0)
|
||||
- Dual VFO Dial Lock (vfoA Dial lock)
|
||||
|
@@ -109,7 +109,8 @@ void CatSetFreq(byte fromType)
|
||||
//#define BCD_LEN 9
|
||||
//PROTOCOL : 0x03
|
||||
//Computer <-(frequency)-> TRCV CAT_BUFF
|
||||
void CatGetFreqMode(unsigned long freq, byte fromType)
|
||||
//void CatGetFreqMode(unsigned long freq, byte fromType)
|
||||
void CatGetFreqMode(unsigned long freq) //for remove warning messages
|
||||
{
|
||||
int i;
|
||||
byte tmpValue;
|
||||
@@ -149,15 +150,21 @@ void CatGetFreqMode(unsigned long freq, byte fromType)
|
||||
SendCatData(5);
|
||||
}
|
||||
|
||||
void CatSetSplit(boolean isSplit, byte fromType)
|
||||
//void CatSetSplit(boolean isSplit, byte fromType)
|
||||
void CatSetSplit(boolean isSplit) //for remove warning messages
|
||||
{
|
||||
|
||||
if (isSplit)
|
||||
splitOn = 1;
|
||||
else
|
||||
splitOn = 0;
|
||||
|
||||
Serial.write(ACK);
|
||||
}
|
||||
|
||||
void CatSetPTT(boolean isPTTOn, byte fromType)
|
||||
{
|
||||
if (fromType == 2 || fromType == 3) {
|
||||
//
|
||||
if ((!inTx) && (fromType == 2 || fromType == 3)) {
|
||||
Serial.write(ACK);
|
||||
return;
|
||||
}
|
||||
@@ -193,7 +200,7 @@ void CatSetPTT(boolean isPTTOn, byte fromType)
|
||||
void CatVFOToggle(boolean isSendACK, byte fromType)
|
||||
{
|
||||
if (fromType != 2 && fromType != 3) {
|
||||
menuVfoToggle(1, 0);
|
||||
menuVfoToggle(1);
|
||||
}
|
||||
|
||||
if (isSendACK)
|
||||
@@ -232,7 +239,8 @@ void CatSetMode(byte tmpMode, byte fromType)
|
||||
}
|
||||
|
||||
//Read EEProm by uBITX Manager Software
|
||||
void ReadEEPRom(byte fromType)
|
||||
//void ReadEEPRom(byte fromType)
|
||||
void ReadEEPRom() //for remove warnings.
|
||||
{
|
||||
//5BYTES
|
||||
//CAT_BUFF[0] [1] [2] [3] [4] //4 COMMAND
|
||||
@@ -255,7 +263,8 @@ void ReadEEPRom(byte fromType)
|
||||
}
|
||||
|
||||
//Write just proecess 1byes
|
||||
void WriteEEPRom(byte fromType)
|
||||
//void WriteEEPRom(byte fromType)
|
||||
void WriteEEPRom(void) //for remove warning
|
||||
{
|
||||
//5BYTES
|
||||
uint16_t eepromStartIndex = CAT_BUFF[0] + CAT_BUFF[1] * 256;
|
||||
@@ -275,7 +284,8 @@ void WriteEEPRom(byte fromType)
|
||||
}
|
||||
}
|
||||
|
||||
void ReadEEPRom_FT817(byte fromType)
|
||||
//void ReadEEPRom_FT817(byte fromType)
|
||||
void ReadEEPRom_FT817(void) //for remove warnings
|
||||
{
|
||||
byte temp0 = CAT_BUFF[0];
|
||||
byte temp1 = CAT_BUFF[1];
|
||||
@@ -601,7 +611,36 @@ void WriteEEPRom_FT817(byte fromType)
|
||||
Serial.write(ACK);
|
||||
}
|
||||
|
||||
void CatRxStatus(byte fromType)
|
||||
const byte anlogPinIndex[6] = {A0, A1, A2, A3, A6, A7};
|
||||
|
||||
//Read ADC Value by uBITX Manager Software
|
||||
void ReadADCValue(void)
|
||||
{
|
||||
//ADC MAP for uBITX
|
||||
int readedADCValue;
|
||||
//5BYTES
|
||||
//CAT_BUFF[0] [1] [2] [3] [4] //4 COMMAND
|
||||
//0 READ ADDRESS
|
||||
readedADCValue = analogRead(anlogPinIndex[CAT_BUFF[0]]);
|
||||
CAT_BUFF[0] = readedADCValue >> 8;
|
||||
CAT_BUFF[1] = readedADCValue;
|
||||
SendCatData(2);
|
||||
Serial.write(ACK);
|
||||
}
|
||||
|
||||
void SetIFSValue(void)
|
||||
{
|
||||
//Set IFShift Value
|
||||
isIFShift = CAT_BUFF[0];
|
||||
ifShiftValue = CAT_BUFF[1] + CAT_BUFF[2] * 256;
|
||||
setFrequency(frequency);
|
||||
SetCarrierFreq();
|
||||
updateLine2Buffer(1); //option, perhap not need
|
||||
Serial.write(ACK);
|
||||
}
|
||||
|
||||
//void CatRxStatus(byte fromType)
|
||||
void CatRxStatus(void) //for remove warning
|
||||
{
|
||||
byte sMeterValue = 1;
|
||||
|
||||
@@ -621,7 +660,8 @@ void CatRxStatus(byte fromType)
|
||||
}
|
||||
|
||||
|
||||
void CatTxStatus(byte fromType)
|
||||
//void CatTxStatus(byte fromType)
|
||||
void CatTxStatus(void) //for remove warning
|
||||
{
|
||||
boolean isHighSWR = false;
|
||||
boolean isSplitOn = false;
|
||||
@@ -722,11 +762,11 @@ void Check_Cat(byte fromType)
|
||||
|
||||
case 0x02 : //Split On
|
||||
case 0x82: //Split Off
|
||||
CatSetSplit(CAT_BUFF[4] == 0x02, fromType);
|
||||
CatSetSplit(CAT_BUFF[4] == 0x02);
|
||||
break;
|
||||
|
||||
case 0x03 : //Read Frequency and mode
|
||||
CatGetFreqMode(frequency, fromType);
|
||||
CatGetFreqMode(frequency);
|
||||
break;
|
||||
|
||||
case 0x07 : //Set Operating Mode
|
||||
@@ -743,24 +783,32 @@ void Check_Cat(byte fromType)
|
||||
break;
|
||||
|
||||
case 0xDB: //Read uBITX EEPROM Data
|
||||
ReadEEPRom(fromType); //Call by uBITX Manager Program
|
||||
ReadEEPRom(); //Call by uBITX Manager Program
|
||||
break;
|
||||
case 0xBB: //Read FT-817 EEPROM Data (for comfirtable)
|
||||
ReadEEPRom_FT817(fromType);
|
||||
ReadEEPRom_FT817();
|
||||
break;
|
||||
|
||||
case 0xDC: //Write uBITX EEPROM Data
|
||||
WriteEEPRom(fromType); //Call by uBITX Manager Program
|
||||
WriteEEPRom(); //Call by uBITX Manager Program
|
||||
break;
|
||||
case 0xBC: //Write FT-817 EEPROM Data (for comfirtable)
|
||||
WriteEEPRom_FT817(fromType);
|
||||
break;
|
||||
|
||||
case 0xDD: //Read uBITX ADC Data
|
||||
ReadADCValue(); //Call by uBITX Manager Program
|
||||
break;
|
||||
|
||||
case 0xDE: //IF-Shift Control by CAT
|
||||
SetIFSValue(); //
|
||||
break;
|
||||
|
||||
case 0xE7 : //Read RX Status
|
||||
CatRxStatus(fromType);
|
||||
CatRxStatus();
|
||||
break;
|
||||
case 0xF7: //Read TX Status
|
||||
CatTxStatus(fromType);
|
||||
CatTxStatus();
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
|
@@ -36,7 +36,7 @@
|
||||
//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, 0b00111000}; //S ~ Z
|
||||
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};
|
||||
@@ -297,15 +297,16 @@ void controlAutoCW(){
|
||||
displayScrolStep = 0;
|
||||
}
|
||||
|
||||
printLineFromEEPRom(0, 2, cwStartIndex + displayScrolStep + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ);
|
||||
printLineFromEEPRom(0, 2, cwStartIndex + displayScrolStep + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ, 0);
|
||||
|
||||
byte diplayAutoCWLine = 0;
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayAutoCWLine = 1;
|
||||
|
||||
lcd.setCursor(0, diplayAutoCWLine);
|
||||
lcd.write(byteToChar(selectedCWTextIndex));
|
||||
lcd.write(':');
|
||||
//byte diplayAutoCWLine = 0;
|
||||
//if ((displayOption1 & 0x01) == 0x01)
|
||||
// diplayAutoCWLine = 1;
|
||||
|
||||
Display_AutoKeyTextIndex(selectedCWTextIndex);
|
||||
//lcd.setCursor(0, diplayAutoCWLine);
|
||||
//lcd.write(byteToChar(selectedCWTextIndex));
|
||||
//lcd.write(':');
|
||||
isNeedScroll = (cwEndIndex - cwStartIndex) > 14 ? 1 : 0;
|
||||
scrollDispayTime = millis() + scrollSpeed;
|
||||
beforeCWTextIndex = selectedCWTextIndex;
|
||||
@@ -365,6 +366,11 @@ void controlAutoCW(){
|
||||
//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
|
||||
|
81
ubitx_20/ubitx.h
Normal file
81
ubitx_20/ubitx.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*************************************************************************
|
||||
header file for C++ by 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/>.
|
||||
**************************************************************************/
|
||||
#define WSPR_COUNT 443 //WSPR_MESSAGE_COUNT
|
||||
#define WSPR_MESSAGE1 444 //
|
||||
#define WSPR_MESSAGE2 490 //
|
||||
#define WSPR_MESSAGE3 536 //
|
||||
#define WSPR_MESSAGE4 582 //
|
||||
|
||||
#define WSPR_BAND_COUNT 3
|
||||
|
||||
#define TX_SSB 0
|
||||
#define TX_CW 1
|
||||
|
||||
|
||||
extern void printLine1(const char *c);
|
||||
extern void printLine2(const char *c);
|
||||
extern void printLineF(char linenmbr, const __FlashStringHelper *c);
|
||||
extern void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetType);
|
||||
extern byte delay_background(unsigned delayTime, byte fromType);
|
||||
extern int btnDown(void);
|
||||
extern char c[30];
|
||||
extern char b[30];
|
||||
extern int enc_read(void);
|
||||
|
||||
extern unsigned long frequency;
|
||||
|
||||
#define printLineF1(x) (printLineF(1, x))
|
||||
#define printLineF2(x) (printLineF(0, x))
|
||||
|
||||
|
||||
/**
|
||||
* The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig.
|
||||
* This assignment is as follows :
|
||||
* Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
||||
* GND +5V CLK0 GND GND CLK1 GND GND CLK2 GND D2 D3 D4 D5 D6 D7
|
||||
* These too are flexible with what you may do with them, for the Raduino, we use them to :
|
||||
* - TX_RX line : Switches between Transmit and Receive after sensing the PTT or the morse keyer
|
||||
* - CW_KEY line : turns on the carrier for CW
|
||||
*/
|
||||
|
||||
#define TX_RX (7)
|
||||
#define CW_TONE (6)
|
||||
#define TX_LPF_A (5)
|
||||
#define TX_LPF_B (4)
|
||||
#define TX_LPF_C (3)
|
||||
#define CW_KEY (2)
|
||||
|
||||
//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes
|
||||
//these are the parameter passed to startTx
|
||||
#define TX_SSB 0
|
||||
#define TX_CW 1
|
||||
|
||||
extern void si5351bx_init(void);
|
||||
extern void si5351bx_setfreq(uint8_t clknum, uint32_t fout);
|
||||
extern void si5351_set_calibration(int32_t cal);
|
||||
extern void initOscillators(void);
|
||||
extern void Set_WSPR_Param(void);
|
||||
extern void TXSubFreq(unsigned long P2);
|
||||
|
||||
extern void startTx(byte txMode, byte isDisplayUpdate);
|
||||
extern void stopTx(void);
|
||||
extern void setTXFilters(unsigned long freq);
|
||||
|
||||
extern void SendWSPRManage(void);
|
||||
extern byte WsprMSGCount;
|
||||
|
||||
|
@@ -1,8 +1,25 @@
|
||||
//Firmware Version
|
||||
#define FIRMWARE_VERSION_INFO F("CE v1.070")
|
||||
#define FIRMWARE_VERSION_NUM 0x02 //1st Complete Project : 1 (Version 1.061), 2st Project : 2
|
||||
|
||||
//Depending on the type of LCD mounted on the uBITX, uncomment one of the options below.
|
||||
//You must select only one.
|
||||
|
||||
#define UBITX_DISPLAY_LCD1602P //LCD mounted on unmodified uBITX
|
||||
//#define UBITX_DISPLAY_LCD1602I //I2C type 16 x 02 LCD
|
||||
//#define UBITX_DISPLAY_LCD2404P //24 x 04 LCD
|
||||
//#define UBITX_DISPLAY_LCD2404I //I2C type 24 x 04 LCD
|
||||
|
||||
//Compile Option
|
||||
#define ENABLE_FACTORYALIGN
|
||||
#define ENABLE_ADCMONITOR //Starting with Version 1.07, you can read ADC values directly from uBITX Manager. So this function is not necessary.
|
||||
|
||||
|
||||
/**
|
||||
Since KD8CEC Version 0.29, most of the original code is no longer available.
|
||||
Cat Suppoort uBITX CEC Version
|
||||
Most features(TX, Frequency Range, Ham Band, TX Control, CW delay, start Delay... more) have been added by KD8CEC.
|
||||
However, the license rules are subject to the original source rules.
|
||||
DE Ian KD8CEC
|
||||
Ian KD8CEC
|
||||
|
||||
Original source comment -------------------------------------------------------------
|
||||
* This source file is under General Public License version 3.
|
||||
@@ -38,6 +55,7 @@
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include <EEPROM.h>
|
||||
#include "ubitx.h"
|
||||
|
||||
/**
|
||||
The main chip which generates upto three oscillators of various frequencies in the
|
||||
@@ -86,25 +104,6 @@
|
||||
#define ANALOG_SPARE (A7)
|
||||
#define ANALOG_SMETER (A7) //by KD8CEC
|
||||
|
||||
/**
|
||||
* The Raduino board is the size of a standard 16x2 LCD panel. It has three connectors:
|
||||
*
|
||||
* First, is an 8 pin connector that provides +5v, GND and six analog input pins that can also be
|
||||
* configured to be used as digital input or output pins. These are referred to as A0,A1,A2,
|
||||
* A3,A6 and A7 pins. The A4 and A5 pins are missing from this connector as they are used to
|
||||
* talk to the Si5351 over I2C protocol.
|
||||
*
|
||||
* Second is a 16 pin LCD connector. This connector is meant specifically for the standard 16x2
|
||||
* LCD display in 4 bit mode. The 4 bit mode requires 4 data lines and two control lines to work:
|
||||
* Lines used are : RESET, ENABLE, D4, D5, D6, D7
|
||||
* We include the library and declare the configuration of the LCD panel too
|
||||
*/
|
||||
|
||||
#include <LiquidCrystal.h>
|
||||
LiquidCrystal lcd(8,9,10,11,12,13);
|
||||
|
||||
#define VERSION_NUM 0x01 //for KD8CEC'S firmware and for memory management software
|
||||
|
||||
/**
|
||||
* The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory.
|
||||
* We have to be very careful with variables that are declared inside the functions as they are
|
||||
@@ -116,8 +115,6 @@ LiquidCrystal lcd(8,9,10,11,12,13);
|
||||
* the input and output from the USB port. We must keep a count of the bytes used while reading
|
||||
* the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable.
|
||||
*/
|
||||
char c[30], b[30];
|
||||
char printBuff[2][17]; //mirrors what is showing on the two lines of the display
|
||||
int count = 0; //to generally count ticks, loops, etc
|
||||
|
||||
/**
|
||||
@@ -150,17 +147,23 @@ int count = 0; //to generally count ticks, loops, etc
|
||||
#define CW_SIDETONE 24
|
||||
#define CW_SPEED 28
|
||||
|
||||
//AT328 has 1KBytes EEPROM
|
||||
//KD8CEC EEPROM MAP
|
||||
#define ADVANCED_FREQ_OPTION1 240 //Bit0: use IFTune_Value, Bit1 : use Stored enabled SDR Mode, Bit2 : dynamic sdr frequency
|
||||
#define IF1_CAL 241
|
||||
#define ENABLE_SDR 242
|
||||
#define SDR_FREQUNCY 243
|
||||
|
||||
#define CW_CAL 252
|
||||
#define VFO_A_MODE 256
|
||||
#define VFO_B_MODE 257
|
||||
#define CW_DELAY 258
|
||||
#define CW_START 259
|
||||
#define HAM_BAND_COUNT 260 //
|
||||
#define TX_TUNE_TYPE 261 //
|
||||
#define HAM_BAND_RANGE 262 //FROM (2BYTE) TO (2BYTE) * 10 = 40byte
|
||||
#define HAM_BAND_FREQS 302 //40, 1 BAND = 4Byte most bit is mode
|
||||
#define TUNING_STEP 342 //TUNING STEP * 6 (index 1 + STEPS 5)
|
||||
#define HAM_BAND_COUNT 260 //
|
||||
#define TX_TUNE_TYPE 261 //
|
||||
#define HAM_BAND_RANGE 262 //FROM (2BYTE) TO (2BYTE) * 10 = 40byte
|
||||
#define HAM_BAND_FREQS 302 //40, 1 BAND = 4Byte most bit is mode
|
||||
#define TUNING_STEP 342 //TUNING STEP * 6 (index 1 + STEPS 5) //1STEP :
|
||||
|
||||
|
||||
//for reduce cw key error, eeprom address
|
||||
#define CW_ADC_MOST_BIT1 348 //most 2bits of DOT_TO , DOT_FROM, ST_TO, ST_FROM
|
||||
@@ -175,10 +178,24 @@ int count = 0; //to generally count ticks, loops, etc
|
||||
#define CW_ADC_BOTH_FROM 356 //CW ADC Range BOTH from (Lower 8 bit)
|
||||
#define CW_ADC_BOTH_TO 357 //CW ADC Range BOTH to (Lower 8 bit)
|
||||
#define CW_KEY_TYPE 358
|
||||
#define CW_DISPLAY_SHIFT 359 //Transmits on CWL, CWU Mode, LCD Frequency shifts Sidetone Frequency.
|
||||
//(7:Enable / Disable //0: enable, 1:disable, (default is applied shift)
|
||||
//6 : 0 : Adjust Pulus, 1 : Adjust Minus
|
||||
//0~5: Adjust Value : * 10 = Adjust Value (0~300)
|
||||
#define COMMON_OPTION0 360 //0: Confirm : CW Frequency Shift
|
||||
//1 : IF Shift Save
|
||||
//
|
||||
//
|
||||
//
|
||||
#define IF_SHIFTVALUE 363
|
||||
|
||||
#define DISPLAY_OPTION1 361 //Display Option1
|
||||
#define DISPLAY_OPTION2 362 //Display Option2
|
||||
|
||||
#define CHANNEL_FREQ 630 //Channel 1 ~ 20, 1 Channel = 4 bytes
|
||||
#define CHANNEL_DESC 710 //Channel 1 ~ 20, 1 Channel = 4 bytes
|
||||
#define RESERVE3 770 //Reserve3 between Channel and Firmware id check
|
||||
|
||||
//Check Firmware type and version
|
||||
#define FIRMWAR_ID_ADDR 776 //776 : 0x59, 777 :0x58, 778 : 0x68 : Id Number, if not found id, erase eeprom(32~1023) for prevent system error.
|
||||
#define VERSION_ADDRESS 779 //check Firmware version
|
||||
@@ -260,9 +277,10 @@ byte sideToneSub = 0;
|
||||
//DialLock
|
||||
byte isDialLock = 0; //000000[0]vfoB [0]vfoA 0Bit : A, 1Bit : B
|
||||
byte isTxType = 0; //000000[0 - isSplit] [0 - isTXStop]
|
||||
byte arTuneStep[5];
|
||||
long arTuneStep[5];
|
||||
byte tuneStepIndex; //default Value 0, start Offset is 0 because of check new user
|
||||
|
||||
byte commonOption0 = 0;
|
||||
byte displayOption1 = 0;
|
||||
byte displayOption2 = 0;
|
||||
|
||||
@@ -280,6 +298,9 @@ bool Iambic_Key = true;
|
||||
#define IAMBICB 0x10 // 0 for Iambic A, 1 for Iambic B
|
||||
unsigned char keyerControl = IAMBICB;
|
||||
|
||||
byte isShiftDisplayCWFreq = 1; //Display Frequency
|
||||
int shiftDisplayAdjustVal = 0; //
|
||||
|
||||
//Variables for auto cw mode
|
||||
byte isCWAutoMode = 0; //0 : none, 1 : CW_AutoMode_Menu_Selection, 2 : CW_AutoMode Sending
|
||||
byte cwAutoTextCount = 0; //cwAutoText Count
|
||||
@@ -312,9 +333,19 @@ unsigned long dbgCount = 0; //not used now
|
||||
unsigned char txFilter = 0; //which of the four transmit filters are in use
|
||||
boolean modeCalibrate = false;//this mode of menus shows extended menus to calibrate the oscillators and choose the proper
|
||||
//beat frequency
|
||||
|
||||
byte advancedFreqOption1; //255 : Bit0: use IFTune_Value, Bit1 : use Stored enabled SDR Mode, Bit2 : dynamic sdr frequency
|
||||
byte attLevel = 0; //ATT : RF Gain Control (Receive) <-- IF1 Shift, 0 : Off, ShiftValue is attLevel * 100; attLevel 150 = 15K
|
||||
char if1TuneValue = 0; //0 : OFF, IF1 + if1TuneValue * 100; // + - 12500;
|
||||
byte sdrModeOn = 0; //SDR MODE ON / OFF
|
||||
unsigned long SDR_Center_Freq; //DEFAULT Frequency : 32000000
|
||||
|
||||
unsigned long beforeIdle_ProcessTime = 0; //for check Idle time
|
||||
byte line2DisplayStatus = 0; //0:Clear, 1 : menu, 1: DisplayFrom Idle,
|
||||
char lcdMeter[17];
|
||||
|
||||
byte isIFShift = 0; //1 = ifShift, 2 extend
|
||||
int ifShiftValue = 0; //
|
||||
|
||||
/**
|
||||
* Below are the basic functions that control the uBitx. Understanding the functions before
|
||||
@@ -377,7 +408,7 @@ void setNextHamBandFreq(unsigned long f, char moveDirection)
|
||||
resultFreq = (unsigned long)(hamBandRange[(unsigned char)findedIndex][0]) * 1000;
|
||||
|
||||
setFrequency(resultFreq);
|
||||
byteWithFreqToMode(loadMode);
|
||||
byteToMode(loadMode, 1);
|
||||
}
|
||||
|
||||
void saveBandFreqByIndex(unsigned long f, unsigned long mode, char bandIndex) {
|
||||
@@ -392,7 +423,6 @@ void saveBandFreqByIndex(unsigned long f, unsigned long mode, char bandIndex) {
|
||||
When the delay is used, the program will generate an error because it is not communicating,
|
||||
so Create a new delay function that can do background processing.
|
||||
*/
|
||||
|
||||
unsigned long delayBeforeTime = 0;
|
||||
byte delay_background(unsigned delayTime, byte fromType){ //fromType : 4 autoCWKey -> Check Paddle
|
||||
delayBeforeTime = millis();
|
||||
@@ -476,31 +506,76 @@ void setTXFilters(unsigned long freq){
|
||||
|
||||
void setFrequency(unsigned long f){
|
||||
f = (f / arTuneStep[tuneStepIndex -1]) * arTuneStep[tuneStepIndex -1];
|
||||
|
||||
setTXFilters(f);
|
||||
|
||||
unsigned long appliedCarrier = ((cwMode == 0 ? usbCarrier : cwmCarrier) + (isIFShift && (inTx == 0) ? ifShiftValue : 0));
|
||||
long if1AdjustValue = ((inTx == 0) ? (attLevel * 100) : 0) + (if1TuneValue * 100); //if1Tune RX, TX Enabled, ATT : only RX Mode
|
||||
|
||||
if (sdrModeOn && (inTx == 0)) //IF SDR
|
||||
{
|
||||
//Fixed Frequency SDR (Default Frequency : 32Mhz, available change sdr Frequency by uBITX Manager)
|
||||
//Dynamic Frequency is for SWL without cat
|
||||
//Offset Frequency + Mhz,
|
||||
//Example : Offset Frequency : 30Mhz and current Frequncy is 7.080 => 37.080Mhz
|
||||
// Offset Frequency : 30Mhz and current Frequncy is 14.074 => 34.074Mhz
|
||||
|
||||
//Dynamic Frequency
|
||||
//if (advancedFreqOption1 & 0x04 != 0x00)
|
||||
// if1AdjustValue += (f % 10000000);
|
||||
|
||||
si5351bx_setfreq(2, 44991500 + if1AdjustValue + f);
|
||||
si5351bx_setfreq(1, 44991500
|
||||
+ if1AdjustValue
|
||||
+ SDR_Center_Freq
|
||||
+ ((advancedFreqOption1 & 0x04) == 0x00 ? 0 : (f % 10000000))
|
||||
+ 2390);
|
||||
/*
|
||||
si5351bx_setfreq(2, 44999500 + f);
|
||||
si5351bx_setfreq(1, 44999500 + SDR_Center_Freq + 2390);
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cwMode == 1 || (cwMode == 0 && (!isUSB)))
|
||||
{
|
||||
//CWL(cwMode == 1) or LSB (cwMode == 0 && (!isUSB))
|
||||
si5351bx_setfreq(2, SECOND_OSC_LSB + if1AdjustValue + appliedCarrier + f);
|
||||
//si5351bx_setfreq(1, SECOND_OSC_LSB + if1AdjustValue - (sdrModeOn ? (SDR_Center_Freq- usbCarrier) : 0));
|
||||
si5351bx_setfreq(1, SECOND_OSC_LSB + if1AdjustValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
//CWU (cwMode == 2) or LSB (cwMode == 0 and isUSB)
|
||||
si5351bx_setfreq(2, SECOND_OSC_USB + if1AdjustValue - appliedCarrier + f);
|
||||
//si5351bx_setfreq(1, SECOND_OSC_USB + if1AdjustValue + (sdrModeOn ? (SDR_Center_Freq- usbCarrier) : 0)); //Increase LO Frequency => 1198500 -> 32Mhz
|
||||
si5351bx_setfreq(1, SECOND_OSC_USB + if1AdjustValue); //Increase LO Frequency => 1198500 -> 32Mhz
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (cwMode == 0)
|
||||
{
|
||||
if (isUSB){
|
||||
si5351bx_setfreq(2, SECOND_OSC_USB - usbCarrier + f);
|
||||
si5351bx_setfreq(2, SECOND_OSC_USB - appliedCarrier + f);
|
||||
si5351bx_setfreq(1, SECOND_OSC_USB);
|
||||
}
|
||||
else{
|
||||
si5351bx_setfreq(2, SECOND_OSC_LSB + usbCarrier + f);
|
||||
si5351bx_setfreq(2, SECOND_OSC_LSB + appliedCarrier + f);
|
||||
si5351bx_setfreq(1, SECOND_OSC_LSB);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cwMode == 1){ //CWL
|
||||
si5351bx_setfreq(2, SECOND_OSC_LSB + cwmCarrier + f);
|
||||
si5351bx_setfreq(2, SECOND_OSC_LSB + appliedCarrier + f);
|
||||
si5351bx_setfreq(1, SECOND_OSC_LSB);
|
||||
}
|
||||
else{ //CWU
|
||||
si5351bx_setfreq(2, SECOND_OSC_USB - cwmCarrier + f);
|
||||
si5351bx_setfreq(2, SECOND_OSC_USB - appliedCarrier + f);
|
||||
si5351bx_setfreq(1, SECOND_OSC_USB);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
frequency = f;
|
||||
}
|
||||
@@ -510,7 +585,6 @@ void setFrequency(unsigned long f){
|
||||
* put the uBitx in tx mode. It takes care of rit settings, sideband settings
|
||||
* Note: In cw mode, doesnt key the radio, only puts it in tx mode
|
||||
*/
|
||||
|
||||
void startTx(byte txMode, byte isDisplayUpdate){
|
||||
//Check Hamband only TX //Not found Hamband index by now frequency
|
||||
if (tuneTXType >= 100 && getIndexHambanBbyFreq(ritOn ? ritTxFrequency : frequency) == -1) {
|
||||
@@ -528,21 +602,25 @@ void startTx(byte txMode, byte isDisplayUpdate){
|
||||
ritRxFrequency = frequency;
|
||||
setFrequency(ritTxFrequency);
|
||||
}
|
||||
else if (splitOn == 1) {
|
||||
else
|
||||
{
|
||||
if (splitOn == 1) {
|
||||
if (vfoActive == VFO_B) {
|
||||
vfoActive = VFO_A;
|
||||
frequency = vfoA;
|
||||
byteToMode(vfoA_mode);
|
||||
byteToMode(vfoA_mode, 0);
|
||||
}
|
||||
else if (vfoActive == VFO_A){
|
||||
vfoActive = VFO_B;
|
||||
frequency = vfoB;
|
||||
byteToMode(vfoB_mode);
|
||||
byteToMode(vfoB_mode, 0);
|
||||
}
|
||||
}
|
||||
|
||||
setFrequency(frequency);
|
||||
setFrequency(frequency);
|
||||
} //end of else
|
||||
|
||||
|
||||
SetCarrierFreq();
|
||||
|
||||
if (txMode == TX_CW){
|
||||
//turn off the second local oscillator and the bfo
|
||||
@@ -575,34 +653,32 @@ void startTx(byte txMode, byte isDisplayUpdate){
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
void stopTx(){
|
||||
void stopTx(void){
|
||||
inTx = 0;
|
||||
|
||||
digitalWrite(TX_RX, 0); //turn off the tx
|
||||
|
||||
if (cwMode == 0)
|
||||
si5351bx_setfreq(0, usbCarrier); //set back the carrier oscillator anyway, cw tx switches it off
|
||||
else
|
||||
si5351bx_setfreq(0, cwmCarrier); //set back the carrier oscillator anyway, cw tx switches it off
|
||||
SetCarrierFreq();
|
||||
|
||||
if (ritOn)
|
||||
setFrequency(ritRxFrequency);
|
||||
else if (splitOn == 1) {
|
||||
else
|
||||
{
|
||||
if (splitOn == 1) {
|
||||
//vfo Change
|
||||
if (vfoActive == VFO_B){
|
||||
vfoActive = VFO_A;
|
||||
frequency = vfoA;
|
||||
byteToMode(vfoA_mode);
|
||||
byteToMode(vfoA_mode, 0);
|
||||
}
|
||||
else if (vfoActive == VFO_A){
|
||||
vfoActive = VFO_B;
|
||||
frequency = vfoB;
|
||||
byteToMode(vfoB_mode);
|
||||
byteToMode(vfoB_mode, 0);
|
||||
}
|
||||
setFrequency(frequency);
|
||||
} //end of else
|
||||
else
|
||||
}
|
||||
|
||||
setFrequency(frequency);
|
||||
} //end of else
|
||||
|
||||
updateDisplay();
|
||||
}
|
||||
@@ -637,7 +713,7 @@ void ritDisable(){
|
||||
* flip the T/R line to T and update the display to denote transmission
|
||||
*/
|
||||
|
||||
void checkPTT(){
|
||||
void checkPTT(){
|
||||
//we don't check for ptt when transmitting cw
|
||||
if (cwTimeout > 0)
|
||||
return;
|
||||
@@ -646,7 +722,7 @@ void checkPTT(){
|
||||
startTx(TX_SSB, 1);
|
||||
delay(50); //debounce the PTT
|
||||
}
|
||||
|
||||
|
||||
if (digitalRead(PTT) == 1 && inTx == 1)
|
||||
stopTx();
|
||||
}
|
||||
@@ -666,7 +742,7 @@ void checkButton(){
|
||||
delay(10);
|
||||
Check_Cat(0);
|
||||
}
|
||||
delay(50);//debounce
|
||||
//delay(50);//debounce
|
||||
}
|
||||
|
||||
|
||||
@@ -681,20 +757,18 @@ int encodedSumValue = 0;
|
||||
unsigned long lastTunetime = 0; //if continous moving, skip threshold processing
|
||||
byte lastMovedirection = 0; //0 : stop, 1 : cw, 2 : ccw
|
||||
|
||||
#define skipThresholdTime 100
|
||||
//#define skipThresholdTime 70
|
||||
#define encodeTimeOut 1000
|
||||
|
||||
void doTuningWithThresHold(){
|
||||
int s = 0;
|
||||
unsigned long prev_freq;
|
||||
long incdecValue = 0;
|
||||
|
||||
if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) ||
|
||||
(vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02)))
|
||||
return;
|
||||
|
||||
if (isCWAutoMode == 0 || cwAutoDialType == 1)
|
||||
s = enc_read();
|
||||
s = enc_read();
|
||||
|
||||
//if time is exceeded, it is recognized as an error,
|
||||
//ignore exists values, because of errors
|
||||
@@ -711,7 +785,9 @@ void doTuningWithThresHold(){
|
||||
encodedSumValue += (s > 0 ? 1 : -1);
|
||||
|
||||
//check threshold and operator actions (hold dial speed = continous moving, skip threshold check)
|
||||
if ((lastTunetime < millis() - skipThresholdTime) && ((encodedSumValue * encodedSumValue) <= (threshold * threshold)))
|
||||
//not use continues changing by Threshold
|
||||
//if ((lastTunetime < (millis() - skipThresholdTime)) && ((encodedSumValue * encodedSumValue) <= (threshold * threshold)))
|
||||
if (((encodedSumValue * encodedSumValue) <= (threshold * threshold)))
|
||||
return;
|
||||
|
||||
lastTunetime = millis();
|
||||
@@ -721,7 +797,8 @@ void doTuningWithThresHold(){
|
||||
|
||||
prev_freq = frequency;
|
||||
//incdecValue = tuningStep * s;
|
||||
frequency += (arTuneStep[tuneStepIndex -1] * s * (s * s < 10 ? 1 : 3)); //appield weight (s is speed)
|
||||
//frequency += (arTuneStep[tuneStepIndex -1] * s * (s * s < 10 ? 1 : 3)); //appield weight (s is speed)
|
||||
frequency += (arTuneStep[tuneStepIndex -1] * s); //appield weight (s is speed) //if want need more increase size, change step size
|
||||
|
||||
if (prev_freq < 10000000l && frequency > 10000000l)
|
||||
isUSB = true;
|
||||
@@ -741,9 +818,9 @@ void doRIT(){
|
||||
unsigned long old_freq = frequency;
|
||||
|
||||
if (knob < 0)
|
||||
frequency -= 100l;
|
||||
frequency -= (arTuneStep[tuneStepIndex -1]); //
|
||||
else if (knob > 0)
|
||||
frequency += 100;
|
||||
frequency += (arTuneStep[tuneStepIndex -1]); //
|
||||
|
||||
if (old_freq != frequency){
|
||||
setFrequency(frequency);
|
||||
@@ -751,8 +828,8 @@ void doRIT(){
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
save Frequency and mode to eeprom
|
||||
/*
|
||||
save Frequency and mode to eeprom for Auto Save with protected eeprom cycle, by kd8cec
|
||||
*/
|
||||
void storeFrequencyAndMode(byte saveType)
|
||||
{
|
||||
@@ -784,6 +861,22 @@ void storeFrequencyAndMode(byte saveType)
|
||||
}
|
||||
}
|
||||
|
||||
//calculate step size from 1 byte, compatible uBITX Manager, by KD8CEC
|
||||
unsigned int byteToSteps(byte srcByte) {
|
||||
byte powerVal = (byte)(srcByte >> 6);
|
||||
unsigned int baseVal = srcByte & 0x3F;
|
||||
|
||||
if (powerVal == 1)
|
||||
return baseVal * 10;
|
||||
else if (powerVal == 2)
|
||||
return baseVal * 100;
|
||||
else if (powerVal == 3)
|
||||
return baseVal * 1000;
|
||||
else
|
||||
return baseVal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The settings are read from EEPROM. The first time around, the values may not be
|
||||
* present or out of range, in this case, some intelligent defaults are copied into the
|
||||
@@ -813,7 +906,7 @@ void initSettings(){
|
||||
|
||||
printLineF(1, F("Init EEProm..."));
|
||||
//initial all eeprom
|
||||
for (unsigned int i = 32; i < 1024; i++) //protect Master_cal, usb_cal
|
||||
for (unsigned int i = 64; i < 1024; i++) //protect Master_cal, usb_cal
|
||||
EEPROM.write(i, 0);
|
||||
|
||||
//Write Firmware ID
|
||||
@@ -823,8 +916,8 @@ void initSettings(){
|
||||
}
|
||||
|
||||
//Version Write for Memory Management Software
|
||||
if (EEPROM.read(VERSION_ADDRESS) != VERSION_NUM)
|
||||
EEPROM.write(VERSION_ADDRESS, VERSION_NUM);
|
||||
if (EEPROM.read(VERSION_ADDRESS) != FIRMWARE_VERSION_NUM)
|
||||
EEPROM.write(VERSION_ADDRESS, FIRMWARE_VERSION_NUM);
|
||||
|
||||
EEPROM.get(CW_CAL, cwmCarrier);
|
||||
|
||||
@@ -847,13 +940,14 @@ void initSettings(){
|
||||
else
|
||||
{
|
||||
Iambic_Key = true;
|
||||
if (cwKeyType = 1)
|
||||
if (cwKeyType == 1)
|
||||
keyerControl &= ~IAMBICB;
|
||||
else
|
||||
keyerControl |= IAMBICB;
|
||||
}
|
||||
|
||||
|
||||
EEPROM.get(COMMON_OPTION0, commonOption0);
|
||||
EEPROM.get(DISPLAY_OPTION1, displayOption1);
|
||||
EEPROM.get(DISPLAY_OPTION2, displayOption2);
|
||||
|
||||
@@ -884,13 +978,13 @@ void initSettings(){
|
||||
if ((3 < tuneTXType && tuneTXType < 100) || 103 < tuneTXType || useHamBandCount < 1 || findedValidValueCount < 5)
|
||||
{
|
||||
tuneTXType = 2;
|
||||
//if empty band Information, auto insert default region 1 frequency range
|
||||
//if empty band Information, auto insert default region 2 frequency range
|
||||
//This part is made temporary for people who have difficulty setting up, so can remove it when you run out of memory.
|
||||
useHamBandCount = 10;
|
||||
hamBandRange[0][0] = 1810; hamBandRange[0][1] = 2000;
|
||||
hamBandRange[1][0] = 3500; hamBandRange[1][1] = 3800;
|
||||
hamBandRange[2][0] = 5351; hamBandRange[2][1] = 5367;
|
||||
hamBandRange[3][0] = 7000; hamBandRange[3][1] = 7300; //region 1
|
||||
hamBandRange[3][0] = 7000; hamBandRange[3][1] = 7300; //region 2
|
||||
hamBandRange[4][0] = 10100; hamBandRange[4][1] = 10150;
|
||||
hamBandRange[5][0] = 14000; hamBandRange[5][1] = 14350;
|
||||
hamBandRange[6][0] = 18068; hamBandRange[6][1] = 18168;
|
||||
@@ -904,8 +998,8 @@ void initSettings(){
|
||||
findedValidValueCount = 0;
|
||||
EEPROM.get(TUNING_STEP, tuneStepIndex);
|
||||
for (byte i = 0; i < 5; i++) {
|
||||
arTuneStep[i] = EEPROM.read(TUNING_STEP + i + 1);
|
||||
if (arTuneStep[i] >= 1 && arTuneStep[i] < 251) //Maximum 250 for check valid Value
|
||||
arTuneStep[i] = byteToSteps(EEPROM.read(TUNING_STEP + i + 1));
|
||||
if (arTuneStep[i] >= 1 && arTuneStep[i] <= 60000) //Maximum 650 for check valid Value
|
||||
findedValidValueCount++;
|
||||
}
|
||||
|
||||
@@ -938,6 +1032,52 @@ void initSettings(){
|
||||
cwAdcBothFrom = EEPROM.read(CW_ADC_BOTH_FROM) | ((tmpMostBits & 0x30) << 4);
|
||||
cwAdcBothTo = EEPROM.read(CW_ADC_BOTH_TO) | ((tmpMostBits & 0xC0) << 2);
|
||||
|
||||
//Display Type for CW mode
|
||||
isShiftDisplayCWFreq = EEPROM.read(CW_DISPLAY_SHIFT);
|
||||
|
||||
//Enable / Diable Check for CW Display Cofiguration Group
|
||||
if ((commonOption0 & 0x80) != 0x00)
|
||||
{
|
||||
//Adjust CW Mode Freq
|
||||
shiftDisplayAdjustVal = (isShiftDisplayCWFreq & 0x3F) * 10;
|
||||
|
||||
//check Minus
|
||||
if ((isShiftDisplayCWFreq & 0x40) == 0x40)
|
||||
shiftDisplayAdjustVal = shiftDisplayAdjustVal * -1;
|
||||
|
||||
//Shift Display Check (Default : 0)
|
||||
if ((isShiftDisplayCWFreq & 0x80) == 0) //Enabled
|
||||
isShiftDisplayCWFreq = 1;
|
||||
else //Disabled
|
||||
isShiftDisplayCWFreq = 0;
|
||||
}
|
||||
|
||||
//Stored IF Shift Option
|
||||
if ((commonOption0 & 0x40) != 0x00)
|
||||
{
|
||||
EEPROM.get(IF_SHIFTVALUE, ifShiftValue);
|
||||
isIFShift = ifShiftValue != 0;
|
||||
}
|
||||
|
||||
//Advanced Freq control
|
||||
EEPROM.get(ADVANCED_FREQ_OPTION1, advancedFreqOption1);
|
||||
|
||||
//use Advanced Frequency Control
|
||||
if (advancedFreqOption1 & 0x01 != 0x00)
|
||||
{
|
||||
EEPROM.get(IF1_CAL, if1TuneValue);
|
||||
|
||||
//Stored Enabled SDR Mode
|
||||
if (advancedFreqOption1 & 0x02 != 0x00)
|
||||
{
|
||||
EEPROM.get(ENABLE_SDR, sdrModeOn);
|
||||
}
|
||||
}
|
||||
|
||||
EEPROM.get(SDR_FREQUNCY, SDR_Center_Freq);
|
||||
if (SDR_Center_Freq == 0)
|
||||
SDR_Center_Freq = 32000000;
|
||||
|
||||
//default Value (for original hardware)
|
||||
if (cwAdcSTFrom >= cwAdcSTTo)
|
||||
{
|
||||
@@ -974,19 +1114,19 @@ void initSettings(){
|
||||
|
||||
//original code with modified by kd8cec
|
||||
if (usbCarrier > 12010000l || usbCarrier < 11990000l)
|
||||
usbCarrier = 11995000l;
|
||||
usbCarrier = 11997000l;
|
||||
|
||||
if (cwmCarrier > 12010000l || cwmCarrier < 11990000l)
|
||||
cwmCarrier = 11995000l;
|
||||
cwmCarrier = 11997000l;
|
||||
|
||||
if (vfoA > 35000000l || 3500000l > vfoA) {
|
||||
vfoA = 7150000l;
|
||||
vfoA_mode = 2;
|
||||
vfoA_mode = 2; //LSB
|
||||
}
|
||||
|
||||
if (vfoB > 35000000l || 3500000l > vfoB) {
|
||||
vfoB = 14150000l;
|
||||
vfoB_mode = 3;
|
||||
vfoB_mode = 3; //USB
|
||||
}
|
||||
//end of original code section
|
||||
|
||||
@@ -1012,7 +1152,6 @@ void initSettings(){
|
||||
}
|
||||
|
||||
void initPorts(){
|
||||
|
||||
analogReference(DEFAULT);
|
||||
|
||||
//??
|
||||
@@ -1061,16 +1200,15 @@ void setup()
|
||||
*/
|
||||
|
||||
//Serial.begin(9600);
|
||||
lcd.begin(16, 2);
|
||||
printLineF(1, F("CECBT v0.33"));
|
||||
LCD_Init();
|
||||
printLineF(1, FIRMWARE_VERSION_INFO);
|
||||
|
||||
Init_Cat(38400, SERIAL_8N1);
|
||||
initMeter(); //not used in this build
|
||||
initSettings();
|
||||
|
||||
if (userCallsignLength > 0 && ((userCallsignLength & 0x80) == 0x80)) {
|
||||
userCallsignLength = userCallsignLength & 0x7F;
|
||||
printLineFromEEPRom(0, 0, 0, userCallsignLength -1); //eeprom to lcd use offset (USER_CALLSIGN_DAT)
|
||||
printLineFromEEPRom(0, 0, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT)
|
||||
delay(500);
|
||||
}
|
||||
else {
|
||||
@@ -1081,7 +1219,7 @@ void setup()
|
||||
|
||||
initPorts();
|
||||
|
||||
byteToMode(vfoA_mode);
|
||||
byteToMode(vfoA_mode, 0);
|
||||
initOscillators();
|
||||
|
||||
frequency = vfoA;
|
||||
@@ -1089,18 +1227,13 @@ void setup()
|
||||
setFrequency(vfoA);
|
||||
updateDisplay();
|
||||
|
||||
#ifdef ENABLE_FACTORYALIGN
|
||||
if (btnDown())
|
||||
factory_alignment();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The loop checks for keydown, ptt, function button and tuning.
|
||||
*/
|
||||
//for debug
|
||||
int dbgCnt = 0;
|
||||
byte flasher = 0;
|
||||
|
||||
//Auto save Frequency and Mode with Protected eeprom life by KD8CEC
|
||||
void checkAutoSaveFreqMode()
|
||||
{
|
||||
//when tx or ritOn, disable auto save
|
||||
@@ -1118,18 +1251,8 @@ void checkAutoSaveFreqMode()
|
||||
//check time for Frequency auto save
|
||||
if (millis() - saveCheckTime > saveIntervalSec * 1000)
|
||||
{
|
||||
if (vfoActive == VFO_A)
|
||||
{
|
||||
vfoA = frequency;
|
||||
vfoA_mode = modeToByte();
|
||||
storeFrequencyAndMode(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
vfoB = frequency;
|
||||
vfoB_mode = modeToByte();
|
||||
storeFrequencyAndMode(2);
|
||||
}
|
||||
FrequencyToVFO(1);
|
||||
saveCheckTime = 0; //for reduce cpu use rate
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1147,18 +1270,21 @@ void loop(){
|
||||
|
||||
//tune only when not tranmsitting
|
||||
if (!inTx){
|
||||
if (ritOn)
|
||||
doRIT();
|
||||
else
|
||||
doTuningWithThresHold();
|
||||
if (isCWAutoMode == 0 || cwAutoDialType == 1)
|
||||
{
|
||||
if (ritOn)
|
||||
doRIT();
|
||||
else
|
||||
doTuningWithThresHold();
|
||||
}
|
||||
|
||||
if (isCWAutoMode == 0 && beforeIdle_ProcessTime < millis() - 500) {
|
||||
if (isCWAutoMode == 0 && beforeIdle_ProcessTime < millis() - 250) {
|
||||
idle_process();
|
||||
checkAutoSaveFreqMode(); //move here form out scope for reduce cpu use rate
|
||||
beforeIdle_ProcessTime = millis();
|
||||
}
|
||||
} //end of check TX Status
|
||||
|
||||
//we check CAT after the encoder as it might put the radio into TX
|
||||
Check_Cat(inTx? 1 : 0);
|
||||
checkAutoSaveFreqMode();
|
||||
}
|
||||
|
@@ -1,165 +0,0 @@
|
||||
/*************************************************************************
|
||||
KD8CEC's uBITX Idle time Processing
|
||||
Functions that run at times that do not affect TX, CW, and CAT
|
||||
It is called in 1/10 time unit.
|
||||
-----------------------------------------------------------------------------
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
byte line2Buffer[16];
|
||||
//KD8CEC 200Hz ST
|
||||
//L14.150 200Hz ST
|
||||
//U14.150 +150khz
|
||||
int freqScrollPosition = 0;
|
||||
//Example Line2 Optinal Display
|
||||
void updateLine2Buffer()
|
||||
{
|
||||
unsigned long tmpFreq = 0;
|
||||
|
||||
if (ritOn)
|
||||
{
|
||||
line2Buffer[0] = 'R';
|
||||
line2Buffer[1] = 'i';
|
||||
line2Buffer[2] = 't';
|
||||
line2Buffer[3] = 'T';
|
||||
line2Buffer[4] = 'X';
|
||||
line2Buffer[5] = ':';
|
||||
|
||||
//display frequency
|
||||
tmpFreq = ritTxFrequency;
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (vfoActive == VFO_B)
|
||||
{
|
||||
tmpFreq = vfoA;
|
||||
//line2Buffer[0] = 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpFreq = vfoB;
|
||||
//line2Buffer[0] = 'B';
|
||||
}
|
||||
|
||||
// EXAMPLE 1 & 2
|
||||
//U14.150.100
|
||||
//display frequency
|
||||
for (int i = 9; i >= 0; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 2 || i == 6) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
//EXAMPLE #1
|
||||
if ((displayOption1 & 0x04) == 0x00)
|
||||
line2Buffer[6] = 'k';
|
||||
else
|
||||
{
|
||||
//example #2
|
||||
if (freqScrollPosition++ > 18)
|
||||
{
|
||||
line2Buffer[6] = 'k';
|
||||
if (freqScrollPosition > 25)
|
||||
freqScrollPosition = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
line2Buffer[10] = 'H';
|
||||
line2Buffer[11] = 'z';
|
||||
|
||||
if (freqScrollPosition < 7)
|
||||
{
|
||||
for (int i = 11; i >= 0; i--)
|
||||
if (i - (7 - freqScrollPosition) >= 0)
|
||||
line2Buffer[i] = line2Buffer[i - (7 - freqScrollPosition)];
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 11; i++)
|
||||
if (i + (freqScrollPosition - 7) <= 11)
|
||||
line2Buffer[i] = line2Buffer[i + (freqScrollPosition - 7)];
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
line2Buffer[7] = ' ';
|
||||
|
||||
//Step
|
||||
byte tmpStep = arTuneStep[tuneStepIndex -1];
|
||||
for (int i = 10; i >= 8; i--) {
|
||||
if (tmpStep > 0) {
|
||||
line2Buffer[i] = tmpStep % 10 + 0x30;
|
||||
tmpStep /= 10;
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
line2Buffer[11] = 'H';
|
||||
line2Buffer[12] = 'z';
|
||||
|
||||
line2Buffer[13] = ' ';
|
||||
//if (
|
||||
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
||||
if (cwKeyType == 0)
|
||||
{
|
||||
line2Buffer[14] = 'S';
|
||||
line2Buffer[15] = 'T';
|
||||
}
|
||||
else if (cwKeyType == 1)
|
||||
{
|
||||
line2Buffer[14] = 'I';
|
||||
line2Buffer[15] = 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
line2Buffer[14] = 'I';
|
||||
line2Buffer[15] = 'B';
|
||||
}
|
||||
}
|
||||
|
||||
void idle_process()
|
||||
{
|
||||
//space for user graphic display
|
||||
if (menuOn == 0)
|
||||
{
|
||||
//if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message
|
||||
if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) {
|
||||
updateLine2Buffer();
|
||||
printLine2(line2Buffer);
|
||||
line2DisplayStatus = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -90,13 +90,13 @@ void cwKeyUp(){
|
||||
#define PDLSWAP 0x08 // 0 for normal, 1 for swap
|
||||
#define IAMBICB 0x10 // 0 for Iambic A, 1 for Iambic B
|
||||
enum KSTYPE {IDLE, CHK_DIT, CHK_DAH, KEYED_PREP, KEYED, INTER_ELEMENT };
|
||||
static long ktimer;
|
||||
static unsigned long ktimer;
|
||||
unsigned char keyerState = IDLE;
|
||||
|
||||
//Below is a test to reduce the keying error. do not delete lines
|
||||
//create by KD8CEC for compatible with new CW Logic
|
||||
char update_PaddleLatch(byte isUpdateKeyState) {
|
||||
unsigned char tmpKeyerControl;
|
||||
unsigned char tmpKeyerControl = 0;
|
||||
int paddle = analogRead(ANALOG_KEYER);
|
||||
|
||||
if (paddle >= cwAdcDashFrom && paddle <= cwAdcDashTo)
|
||||
@@ -126,9 +126,7 @@ char update_PaddleLatch(byte isUpdateKeyState) {
|
||||
// modified by KD8CEC
|
||||
******************************************************************************/
|
||||
void cwKeyer(void){
|
||||
byte paddle;
|
||||
lastPaddle = 0;
|
||||
int dot,dash;
|
||||
bool continue_loop = true;
|
||||
unsigned tmpKeyControl = 0;
|
||||
|
||||
@@ -170,14 +168,32 @@ void cwKeyer(void){
|
||||
break;
|
||||
|
||||
case KEYED_PREP:
|
||||
//modified KD8CEC
|
||||
/*
|
||||
ktimer += millis(); // set ktimer to interval end time
|
||||
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
||||
keyerState = KEYED; // next state
|
||||
if (!inTx){
|
||||
//DelayTime Option
|
||||
delay_background(delayBeforeCWStartTime * 2, 2);
|
||||
|
||||
keyDown = 0;
|
||||
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
||||
startTx(TX_CW, 1);
|
||||
}
|
||||
*/
|
||||
if (!inTx){
|
||||
//DelayTime Option
|
||||
delay_background(delayBeforeCWStartTime * 2, 2);
|
||||
|
||||
keyDown = 0;
|
||||
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
||||
startTx(TX_CW, 1);
|
||||
}
|
||||
ktimer += millis(); // set ktimer to interval end time
|
||||
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
||||
keyerState = KEYED; // next state
|
||||
|
||||
cwKeydown();
|
||||
break;
|
||||
|
||||
@@ -206,7 +222,7 @@ void cwKeyer(void){
|
||||
break;
|
||||
}
|
||||
|
||||
Check_Cat(3);
|
||||
Check_Cat(2);
|
||||
} //end of while
|
||||
}
|
||||
else{
|
||||
@@ -214,6 +230,9 @@ void cwKeyer(void){
|
||||
if (update_PaddleLatch(0) == DIT_L) {
|
||||
// if we are here, it is only because the key is pressed
|
||||
if (!inTx){
|
||||
//DelayTime Option
|
||||
delay_background(delayBeforeCWStartTime * 2, 2);
|
||||
|
||||
keyDown = 0;
|
||||
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
||||
startTx(TX_CW, 1);
|
||||
@@ -231,13 +250,14 @@ void cwKeyer(void){
|
||||
keyDown = 0;
|
||||
stopTx();
|
||||
}
|
||||
if (!cwTimeout)
|
||||
return;
|
||||
//if (!cwTimeout) //removed by KD8CEC
|
||||
// return;
|
||||
// got back to the beginning of the loop, if no further activity happens on straight key
|
||||
// we will time out, and return out of this routine
|
||||
//delay(5);
|
||||
delay_background(5, 3);
|
||||
continue;
|
||||
//delay_background(5, 3); //removed by KD8CEC
|
||||
//continue; //removed by KD8CEC
|
||||
return; //Tx stop control by Main Loop
|
||||
}
|
||||
|
||||
Check_Cat(2);
|
||||
|
552
ubitx_20/ubitx_lcd_1602i.ino
Normal file
552
ubitx_20/ubitx_lcd_1602i.ino
Normal file
@@ -0,0 +1,552 @@
|
||||
/*************************************************************************
|
||||
KD8CEC, _______
|
||||
uBITX Display Routine for LCD1602 I2C
|
||||
|
||||
1.Code for 16 x 2 LCD for I2C.
|
||||
2.Display related functions of uBITX. Some functions moved from uBITX_Ui.
|
||||
3.uBITX Idle time Processing
|
||||
Functions that run at times that do not affect TX, CW, and CAT
|
||||
It is called in 1/10 time unit.
|
||||
-----------------------------------------------------------------------------
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
#ifdef UBITX_DISPLAY_LCD1602I
|
||||
|
||||
|
||||
//========================================================================
|
||||
//Begin of LCD Hardware define
|
||||
//========================================================================
|
||||
#include <LiquidCrystal.h>
|
||||
LiquidCrystal lcd(8,9,10,11,12,13);
|
||||
|
||||
|
||||
//========================================================================
|
||||
//End of LCD Hardware define
|
||||
//========================================================================
|
||||
|
||||
//========================================================================
|
||||
//Begin of Display Base Routines (Init, printLine..)
|
||||
//========================================================================
|
||||
char c[30], b[30];
|
||||
char printBuff[2][17]; //mirrors what is showing on the two lines of the display
|
||||
|
||||
const PROGMEM uint8_t meters_bitmap[] = {
|
||||
B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 , //custom 1
|
||||
B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 , //custom 2
|
||||
B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100 , //custom 3
|
||||
B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110 , //custom 4
|
||||
B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 , //custom 5
|
||||
B01000, B11100, B01000, B00000, B10111, B10101, B10101, B10111 //custom 6
|
||||
};
|
||||
|
||||
PGM_P p_metes_bitmap = reinterpret_cast<PGM_P>(meters_bitmap);
|
||||
|
||||
const PROGMEM uint8_t lock_bitmap[8] = {
|
||||
0b01110,
|
||||
0b10001,
|
||||
0b10001,
|
||||
0b11111,
|
||||
0b11011,
|
||||
0b11011,
|
||||
0b11111,
|
||||
0b00000};
|
||||
PGM_P plock_bitmap = reinterpret_cast<PGM_P>(lock_bitmap);
|
||||
|
||||
|
||||
// initializes the custom characters
|
||||
// we start from char 1 as char 0 terminates the string!
|
||||
void initMeter(){
|
||||
uint8_t tmpbytes[8];
|
||||
byte i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(plock_bitmap + i);
|
||||
lcd.createChar(0, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i);
|
||||
lcd.createChar(1, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8);
|
||||
lcd.createChar(2, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16);
|
||||
lcd.createChar(3, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24);
|
||||
lcd.createChar(4, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32);
|
||||
lcd.createChar(5, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40);
|
||||
lcd.createChar(6, tmpbytes);
|
||||
}
|
||||
|
||||
void LCD_Init(void)
|
||||
{
|
||||
lcd.begin(16, 2);
|
||||
initMeter(); //for Meter Display
|
||||
}
|
||||
|
||||
//by KD8CEC
|
||||
//0 ~ 25 : 30 over : + 10
|
||||
void drawMeter(int needle) {
|
||||
//5Char + O over
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (needle >= 5)
|
||||
lcdMeter[i] = 5; //full
|
||||
else if (needle > 0)
|
||||
lcdMeter[i] = needle; //full
|
||||
else //0
|
||||
lcdMeter[i] = 0x20;
|
||||
|
||||
needle -= 5;
|
||||
}
|
||||
|
||||
if (needle > 0)
|
||||
lcdMeter[5] = 6;
|
||||
else
|
||||
lcdMeter[5] = 0x20;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// The generic routine to display one line on the LCD
|
||||
void printLine(unsigned char linenmbr, const char *c) {
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||
|
||||
if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change
|
||||
lcd.setCursor(0, linenmbr); // place the cursor at the beginning of the selected line
|
||||
lcd.print(c);
|
||||
strcpy(printBuff[linenmbr], c);
|
||||
|
||||
for (byte i = strlen(c); i < 16; i++) { // add white spaces until the end of the 16 characters line is reached
|
||||
lcd.write(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printLineF(char linenmbr, const __FlashStringHelper *c)
|
||||
{
|
||||
int i;
|
||||
char tmpBuff[17];
|
||||
PGM_P p = reinterpret_cast<PGM_P>(c);
|
||||
|
||||
for (i = 0; i < 17; i++){
|
||||
unsigned char fChar = pgm_read_byte(p++);
|
||||
tmpBuff[i] = fChar;
|
||||
if (fChar == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
printLine(linenmbr, tmpBuff);
|
||||
}
|
||||
|
||||
#define LCD_MAX_COLUMN 16
|
||||
void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) {
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||
|
||||
lcd.setCursor(lcdColumn, linenmbr);
|
||||
|
||||
for (byte i = eepromStartIndex; i <= eepromEndIndex; i++)
|
||||
{
|
||||
if (++lcdColumn <= LCD_MAX_COLUMN)
|
||||
lcd.write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (byte i = lcdColumn; i < 16; i++) //Right Padding by Space
|
||||
lcd.write(' ');
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1(const char *c){
|
||||
printLine(1,c);
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2(const char *c){
|
||||
printLine(0,c);
|
||||
}
|
||||
|
||||
void clearLine2()
|
||||
{
|
||||
printLine2("");
|
||||
line2DisplayStatus = 0;
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1Clear(){
|
||||
printLine(1,"");
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2Clear(){
|
||||
printLine(0, "");
|
||||
}
|
||||
|
||||
void printLine2ClearAndUpdate(){
|
||||
printLine(0, "");
|
||||
line2DisplayStatus = 0;
|
||||
updateDisplay();
|
||||
}
|
||||
//===================================================================================
|
||||
//End of Display Base Routines
|
||||
//===================================================================================
|
||||
|
||||
//===================================================================================
|
||||
//Begin of User Interface Routines
|
||||
//===================================================================================
|
||||
|
||||
// this builds up the top line of the display with frequency and mode
|
||||
void updateDisplay() {
|
||||
// tks Jack Purdum W8TEE
|
||||
// replaced fsprint commmands by str commands for code size reduction
|
||||
// replace code for Frequency numbering error (alignment, point...) by KD8CEC
|
||||
int i;
|
||||
unsigned long tmpFreq = frequency; //
|
||||
|
||||
memset(c, 0, sizeof(c));
|
||||
|
||||
if (inTx){
|
||||
if (isCWAutoMode == 2) {
|
||||
for (i = 0; i < 4; i++)
|
||||
c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' ');
|
||||
|
||||
//display Sending Index
|
||||
c[4] = byteToChar(sendingCWTextIndex);
|
||||
c[5] = '=';
|
||||
}
|
||||
else {
|
||||
if (cwTimeout > 0)
|
||||
strcpy(c, " CW:");
|
||||
else
|
||||
strcpy(c, " TX:");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ritOn)
|
||||
strcpy(c, "RIT ");
|
||||
else {
|
||||
if (cwMode == 0)
|
||||
{
|
||||
if (isUSB)
|
||||
strcpy(c, "USB ");
|
||||
else
|
||||
strcpy(c, "LSB ");
|
||||
}
|
||||
else if (cwMode == 1)
|
||||
{
|
||||
strcpy(c, "CWL ");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(c, "CWU ");
|
||||
}
|
||||
}
|
||||
if (vfoActive == VFO_A) // VFO A is active
|
||||
strcat(c, "A:");
|
||||
else
|
||||
strcat(c, "B:");
|
||||
}
|
||||
|
||||
//Fixed by Mitani Massaru (JE4SMQ)
|
||||
if (isShiftDisplayCWFreq == 1)
|
||||
{
|
||||
if (cwMode == 1) //CWL
|
||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
||||
else if (cwMode == 2) //CWU
|
||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
||||
}
|
||||
|
||||
//display frequency
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) c[i] = '.';
|
||||
else {
|
||||
c[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
c[i] = ' ';
|
||||
}
|
||||
|
||||
//remarked by KD8CEC
|
||||
//already RX/TX status display, and over index (16 x 2 LCD)
|
||||
//if (inTx)
|
||||
// strcat(c, " TX");
|
||||
printLine(1, c);
|
||||
|
||||
byte diplayVFOLine = 1;
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayVFOLine = 0;
|
||||
|
||||
if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) ||
|
||||
(vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) {
|
||||
lcd.setCursor(5,diplayVFOLine);
|
||||
lcd.write((uint8_t)0);
|
||||
}
|
||||
else if (isCWAutoMode == 2){
|
||||
lcd.setCursor(5,diplayVFOLine);
|
||||
lcd.write(0x7E);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd.setCursor(5,diplayVFOLine);
|
||||
lcd.write(':');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char line2Buffer[16];
|
||||
//KD8CEC 200Hz ST
|
||||
//L14.150 200Hz ST
|
||||
//U14.150 +150khz
|
||||
int freqScrollPosition = 0;
|
||||
//Example Line2 Optinal Display
|
||||
//immediate execution, not call by scheulder
|
||||
void updateLine2Buffer(char displayType)
|
||||
{
|
||||
unsigned long tmpFreq = 0;
|
||||
if (ritOn)
|
||||
{
|
||||
strcpy(line2Buffer, "RitTX:");
|
||||
|
||||
//display frequency
|
||||
tmpFreq = ritTxFrequency;
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
return;
|
||||
} //end of ritOn display
|
||||
|
||||
//======================================================
|
||||
//other VFO display
|
||||
//======================================================
|
||||
if (vfoActive == VFO_B)
|
||||
{
|
||||
tmpFreq = vfoA;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpFreq = vfoB;
|
||||
}
|
||||
|
||||
// EXAMPLE 1 & 2
|
||||
//U14.150.100
|
||||
//display frequency
|
||||
for (int i = 9; i >= 0; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 2 || i == 6) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
//EXAMPLE #1
|
||||
if ((displayOption1 & 0x04) == 0x00) //none scroll display
|
||||
line2Buffer[6] = 'k';
|
||||
else
|
||||
{
|
||||
//example #2
|
||||
if (freqScrollPosition++ > 18) //none scroll display time
|
||||
{
|
||||
line2Buffer[6] = 'k';
|
||||
if (freqScrollPosition > 25)
|
||||
freqScrollPosition = -1;
|
||||
}
|
||||
else //scroll frequency
|
||||
{
|
||||
line2Buffer[10] = 'H';
|
||||
line2Buffer[11] = 'z';
|
||||
|
||||
if (freqScrollPosition < 7)
|
||||
{
|
||||
for (int i = 11; i >= 0; i--)
|
||||
if (i - (7 - freqScrollPosition) >= 0)
|
||||
line2Buffer[i] = line2Buffer[i - (7 - freqScrollPosition)];
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 11; i++)
|
||||
if (i + (freqScrollPosition - 7) <= 11)
|
||||
line2Buffer[i] = line2Buffer[i + (freqScrollPosition - 7)];
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
}
|
||||
} //scroll
|
||||
|
||||
line2Buffer[7] = ' ';
|
||||
|
||||
if (isIFShift)
|
||||
{
|
||||
// if (isDirectCall == 1)
|
||||
// for (int i = 0; i < 16; i++)
|
||||
// line2Buffer[i] = ' ';
|
||||
|
||||
//IFShift Offset Value
|
||||
line2Buffer[8] = 'I';
|
||||
line2Buffer[9] = 'F';
|
||||
|
||||
line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0;
|
||||
line2Buffer[11] = 0;
|
||||
line2Buffer[12] = ' ';
|
||||
|
||||
//11, 12, 13, 14, 15
|
||||
memset(b, 0, sizeof(b));
|
||||
ltoa(ifShiftValue, b, DEC);
|
||||
strncat(line2Buffer, b, 5);
|
||||
|
||||
//if (isDirectCall == 1) //if call by encoder (not scheduler), immediate print value
|
||||
printLine2(line2Buffer);
|
||||
} // end of display IF
|
||||
else // step & Key Type display
|
||||
{
|
||||
//if (isDirectCall != 0)
|
||||
// return;
|
||||
|
||||
memset(&line2Buffer[8], ' ', 8);
|
||||
//Step
|
||||
long tmpStep = arTuneStep[tuneStepIndex -1];
|
||||
|
||||
byte isStepKhz = 0;
|
||||
if (tmpStep >= 1000)
|
||||
{
|
||||
isStepKhz = 2;
|
||||
}
|
||||
|
||||
for (int i = 10; i >= 8 - isStepKhz; i--) {
|
||||
if (tmpStep > 0) {
|
||||
line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30;
|
||||
tmpStep /= 10;
|
||||
}
|
||||
else
|
||||
line2Buffer[i +isStepKhz] = ' ';
|
||||
}
|
||||
|
||||
if (isStepKhz == 0)
|
||||
{
|
||||
line2Buffer[11] = 'H';
|
||||
line2Buffer[12] = 'z';
|
||||
}
|
||||
|
||||
line2Buffer[13] = ' ';
|
||||
|
||||
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
||||
if (cwKeyType == 0)
|
||||
{
|
||||
line2Buffer[14] = 'S';
|
||||
line2Buffer[15] = 'T';
|
||||
}
|
||||
else if (cwKeyType == 1)
|
||||
{
|
||||
line2Buffer[14] = 'I';
|
||||
line2Buffer[15] = 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
line2Buffer[14] = 'I';
|
||||
line2Buffer[15] = 'B';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//meterType : 0 = S.Meter, 1 : P.Meter
|
||||
void DisplayMeter(byte meterType, byte meterValue, char drawPosition)
|
||||
{
|
||||
if (meterType == 0 || meterType == 1 || meterType == 2)
|
||||
{
|
||||
drawMeter(meterValue); //call original source code
|
||||
int lineNumber = 0;
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
lineNumber = 1;
|
||||
|
||||
lcd.setCursor(drawPosition, lineNumber);
|
||||
|
||||
for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6
|
||||
lcd.write(lcdMeter[i]);
|
||||
}
|
||||
}
|
||||
|
||||
byte testValue = 0;
|
||||
char checkCount = 0;
|
||||
void idle_process()
|
||||
{
|
||||
//space for user graphic display
|
||||
if (menuOn == 0)
|
||||
{
|
||||
if ((displayOption1 & 0x10) == 0x10) //always empty topline
|
||||
return;
|
||||
|
||||
//if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message
|
||||
if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) {
|
||||
if (checkCount++ > 1)
|
||||
{
|
||||
updateLine2Buffer(0); //call by scheduler
|
||||
printLine2(line2Buffer);
|
||||
line2DisplayStatus = 2;
|
||||
checkCount = 0;
|
||||
}
|
||||
|
||||
//EX for Meters
|
||||
/*
|
||||
DisplayMeter(0, testValue++, 7);
|
||||
if (testValue > 30)
|
||||
testValue = 0;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Display_AutoKeyTextIndex(char textIndex)
|
||||
{
|
||||
byte diplayAutoCWLine = 0;
|
||||
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayAutoCWLine = 1;
|
||||
lcd.setCursor(0, diplayAutoCWLine);
|
||||
lcd.write(byteToChar(selectedCWTextIndex));
|
||||
lcd.write(':');
|
||||
}
|
||||
|
||||
|
||||
#endif
|
694
ubitx_20/ubitx_lcd_1602p.ino
Normal file
694
ubitx_20/ubitx_lcd_1602p.ino
Normal file
@@ -0,0 +1,694 @@
|
||||
/*************************************************************************
|
||||
KD8CEC's uBITX Display Routine for LCD1602 Parrel
|
||||
1.This is the display code for the default LCD mounted in uBITX.
|
||||
2.Display related functions of uBITX. Some functions moved from uBITX_Ui.
|
||||
3.uBITX Idle time Processing
|
||||
Functions that run at times that do not affect TX, CW, and CAT
|
||||
It is called in 1/10 time unit.
|
||||
-----------------------------------------------------------------------------
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
#ifdef UBITX_DISPLAY_LCD1602P
|
||||
|
||||
|
||||
//========================================================================
|
||||
//Begin of TinyLCD Library by KD8CEC
|
||||
//========================================================================
|
||||
/*************************************************************************
|
||||
LCD1602_TINY Library for 16 x 2 LCD
|
||||
Referecnce Source : LiquidCrystal.cpp
|
||||
KD8CEC
|
||||
|
||||
This source code is modified version for small program memory
|
||||
from Arduino LiquidCrystal Library
|
||||
|
||||
I wrote this code myself, so there is no license restriction.
|
||||
So this code allows anyone to write with confidence.
|
||||
But keep it as long as the original author of the code.
|
||||
DE Ian KD8CEC
|
||||
**************************************************************************/
|
||||
#define LCD_Command(x) (LCD_Send(x, LOW))
|
||||
#define LCD_Write(x) (LCD_Send(x, HIGH))
|
||||
|
||||
//Define connected PIN
|
||||
#define LCD_PIN_RS 8
|
||||
#define LCD_PIN_EN 9
|
||||
uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13};
|
||||
|
||||
// commands
|
||||
#define LCD_CLEARDISPLAY 0x01
|
||||
#define LCD_RETURNHOME 0x02
|
||||
#define LCD_ENTRYMODESET 0x04
|
||||
#define LCD_DISPLAYCONTROL 0x08
|
||||
#define LCD_CURSORSHIFT 0x10
|
||||
#define LCD_FUNCTIONSET 0x20
|
||||
#define LCD_SETCGRAMADDR 0x40
|
||||
#define LCD_SETDDRAMADDR 0x80
|
||||
|
||||
// flags for display entry mode
|
||||
#define LCD_ENTRYRIGHT 0x00
|
||||
#define LCD_ENTRYLEFT 0x02
|
||||
#define LCD_ENTRYSHIFTINCREMENT 0x01
|
||||
#define LCD_ENTRYSHIFTDECREMENT 0x00
|
||||
|
||||
// flags for display on/off control
|
||||
#define LCD_DISPLAYON 0x04
|
||||
#define LCD_DISPLAYOFF 0x00
|
||||
#define LCD_CURSORON 0x02
|
||||
#define LCD_CURSOROFF 0x00
|
||||
#define LCD_BLINKON 0x01
|
||||
#define LCD_BLINKOFF 0x00
|
||||
|
||||
// flags for display/cursor shift
|
||||
#define LCD_DISPLAYMOVE 0x08
|
||||
#define LCD_CURSORMOVE 0x00
|
||||
#define LCD_MOVERIGHT 0x04
|
||||
#define LCD_MOVELEFT 0x00
|
||||
|
||||
// flags for function set
|
||||
#define LCD_8BITMODE 0x10
|
||||
#define LCD_4BITMODE 0x00
|
||||
#define LCD_2LINE 0x08
|
||||
#define LCD_1LINE 0x00
|
||||
#define LCD_5x10DOTS 0x04
|
||||
#define LCD_5x8DOTS 0x00
|
||||
|
||||
void write4bits(uint8_t value)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
digitalWrite(LCD_PIN_DAT[i], (value >> i) & 0x01);
|
||||
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(LCD_PIN_EN, HIGH);
|
||||
delayMicroseconds(1); // enable pulse must be >450ns
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
delayMicroseconds(100); // commands need > 37us to settle
|
||||
}
|
||||
|
||||
void LCD_Send(uint8_t value, uint8_t mode)
|
||||
{
|
||||
digitalWrite(LCD_PIN_RS, mode);
|
||||
write4bits(value>>4);
|
||||
write4bits(value);
|
||||
}
|
||||
|
||||
void LCD1602_Init()
|
||||
{
|
||||
pinMode(LCD_PIN_RS, OUTPUT);
|
||||
pinMode(LCD_PIN_EN, OUTPUT);
|
||||
for (int i = 0; i < 4; i++)
|
||||
pinMode(LCD_PIN_DAT[i], OUTPUT);
|
||||
|
||||
delayMicroseconds(50);
|
||||
|
||||
// Now we pull both RS and R/W low to begin commands
|
||||
digitalWrite(LCD_PIN_RS, LOW);
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
|
||||
// we start in 8bit mode, try to set 4 bit mode
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// second try
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// third go!
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(150);
|
||||
|
||||
// finally, set to 4-bit interface
|
||||
write4bits(0x02);
|
||||
|
||||
// finally, set # lines, font size, etc.
|
||||
LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE);
|
||||
|
||||
// turn the display on with no cursor or blinking default
|
||||
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
|
||||
|
||||
// clear it off
|
||||
LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||
delayMicroseconds(2000); // this command takes a long time!
|
||||
|
||||
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
|
||||
}
|
||||
|
||||
void LCD_Print(const char *c)
|
||||
{
|
||||
for (int i = 0; i < strlen(c); i++)
|
||||
{
|
||||
if (*(c + i) == 0x00) return;
|
||||
LCD_Write(*(c + i));
|
||||
}
|
||||
}
|
||||
|
||||
void LCD_SetCursor(uint8_t col, uint8_t row)
|
||||
{
|
||||
LCD_Command(LCD_SETDDRAMADDR | (col + row * 0x40)); //0 : 0x00, 1 : 0x40, only for 16 x 2 lcd
|
||||
}
|
||||
|
||||
void LCD_CreateChar(uint8_t location, uint8_t charmap[])
|
||||
{
|
||||
location &= 0x7; // we only have 8 locations 0-7
|
||||
LCD_Command(LCD_SETCGRAMADDR | (location << 3));
|
||||
for (int i=0; i<8; i++)
|
||||
LCD_Write(charmap[i]);
|
||||
}
|
||||
//========================================================================
|
||||
//End of TinyLCD Library by KD8CEC
|
||||
//========================================================================
|
||||
|
||||
/*
|
||||
#include <LiquidCrystal.h>
|
||||
LiquidCrystal lcd(8,9,10,11,12,13);
|
||||
*/
|
||||
|
||||
|
||||
//========================================================================
|
||||
//Begin of Display Base Routines (Init, printLine..)
|
||||
//========================================================================
|
||||
char c[30], b[30];
|
||||
char printBuff[2][17]; //mirrors what is showing on the two lines of the display
|
||||
|
||||
const PROGMEM uint8_t meters_bitmap[] = {
|
||||
B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 , //custom 1
|
||||
B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 , //custom 2
|
||||
B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100 , //custom 3
|
||||
B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110 , //custom 4
|
||||
B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 , //custom 5
|
||||
B01000, B11100, B01000, B00000, B10111, B10101, B10101, B10111 //custom 6
|
||||
};
|
||||
|
||||
PGM_P p_metes_bitmap = reinterpret_cast<PGM_P>(meters_bitmap);
|
||||
|
||||
const PROGMEM uint8_t lock_bitmap[8] = {
|
||||
0b01110,
|
||||
0b10001,
|
||||
0b10001,
|
||||
0b11111,
|
||||
0b11011,
|
||||
0b11011,
|
||||
0b11111,
|
||||
0b00000};
|
||||
PGM_P plock_bitmap = reinterpret_cast<PGM_P>(lock_bitmap);
|
||||
|
||||
|
||||
// initializes the custom characters
|
||||
// we start from char 1 as char 0 terminates the string!
|
||||
void initMeter(){
|
||||
uint8_t tmpbytes[8];
|
||||
byte i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(plock_bitmap + i);
|
||||
LCD_CreateChar(0, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i);
|
||||
LCD_CreateChar(1, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8);
|
||||
LCD_CreateChar(2, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16);
|
||||
LCD_CreateChar(3, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24);
|
||||
LCD_CreateChar(4, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32);
|
||||
LCD_CreateChar(5, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40);
|
||||
LCD_CreateChar(6, tmpbytes);
|
||||
}
|
||||
|
||||
void LCD_Init(void)
|
||||
{
|
||||
LCD1602_Init();
|
||||
initMeter(); //for Meter Display
|
||||
}
|
||||
|
||||
//by KD8CEC
|
||||
//0 ~ 25 : 30 over : + 10
|
||||
void drawMeter(int needle) {
|
||||
//5Char + O over
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (needle >= 5)
|
||||
lcdMeter[i] = 5; //full
|
||||
else if (needle > 0)
|
||||
lcdMeter[i] = needle; //full
|
||||
else //0
|
||||
lcdMeter[i] = 0x20;
|
||||
|
||||
needle -= 5;
|
||||
}
|
||||
|
||||
if (needle > 0)
|
||||
lcdMeter[5] = 6;
|
||||
else
|
||||
lcdMeter[5] = 0x20;
|
||||
}
|
||||
|
||||
// The generic routine to display one line on the LCD
|
||||
void printLine(unsigned char linenmbr, const char *c) {
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||
if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change
|
||||
LCD_SetCursor(0, linenmbr); // place the cursor at the beginning of the selected line
|
||||
LCD_Print(c);
|
||||
strcpy(printBuff[linenmbr], c);
|
||||
|
||||
for (byte i = strlen(c); i < 16; i++) { // add white spaces until the end of the 16 characters line is reached
|
||||
LCD_Write(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printLineF(char linenmbr, const __FlashStringHelper *c)
|
||||
{
|
||||
int i;
|
||||
char tmpBuff[17];
|
||||
PGM_P p = reinterpret_cast<PGM_P>(c);
|
||||
|
||||
for (i = 0; i < 17; i++){
|
||||
unsigned char fChar = pgm_read_byte(p++);
|
||||
tmpBuff[i] = fChar;
|
||||
if (fChar == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
printLine(linenmbr, tmpBuff);
|
||||
}
|
||||
|
||||
#define LCD_MAX_COLUMN 16
|
||||
void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) {
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||
|
||||
LCD_SetCursor(lcdColumn, linenmbr);
|
||||
|
||||
for (byte i = eepromStartIndex; i <= eepromEndIndex; i++)
|
||||
{
|
||||
if (++lcdColumn <= LCD_MAX_COLUMN)
|
||||
LCD_Write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (byte i = lcdColumn; i < 16; i++) //Right Padding by Space
|
||||
LCD_Write(' ');
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1(const char *c)
|
||||
{
|
||||
printLine(1,c);
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2(const char *c)
|
||||
{
|
||||
printLine(0,c);
|
||||
}
|
||||
|
||||
void clearLine2()
|
||||
{
|
||||
printLine2("");
|
||||
line2DisplayStatus = 0;
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1Clear(){
|
||||
printLine(1,"");
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2Clear(){
|
||||
printLine(0, "");
|
||||
}
|
||||
|
||||
void printLine2ClearAndUpdate(){
|
||||
printLine(0, "");
|
||||
line2DisplayStatus = 0;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
//==================================================================================
|
||||
//End of Display Base Routines
|
||||
//==================================================================================
|
||||
|
||||
|
||||
//==================================================================================
|
||||
//Begin of User Interface Routines
|
||||
//==================================================================================
|
||||
|
||||
//Main Display
|
||||
// this builds up the top line of the display with frequency and mode
|
||||
void updateDisplay() {
|
||||
// tks Jack Purdum W8TEE
|
||||
// replaced fsprint commmands by str commands for code size reduction
|
||||
// replace code for Frequency numbering error (alignment, point...) by KD8CEC
|
||||
int i;
|
||||
unsigned long tmpFreq = frequency; //
|
||||
|
||||
memset(c, 0, sizeof(c));
|
||||
|
||||
if (inTx){
|
||||
if (isCWAutoMode == 2) {
|
||||
for (i = 0; i < 4; i++)
|
||||
c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' ');
|
||||
|
||||
//display Sending Index
|
||||
c[4] = byteToChar(sendingCWTextIndex);
|
||||
c[5] = '=';
|
||||
}
|
||||
else {
|
||||
if (cwTimeout > 0)
|
||||
strcpy(c, " CW:");
|
||||
else
|
||||
strcpy(c, " TX:");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ritOn)
|
||||
strcpy(c, "RIT ");
|
||||
else {
|
||||
if (cwMode == 0)
|
||||
{
|
||||
if (isUSB)
|
||||
strcpy(c, "USB ");
|
||||
else
|
||||
strcpy(c, "LSB ");
|
||||
}
|
||||
else if (cwMode == 1)
|
||||
{
|
||||
strcpy(c, "CWL ");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(c, "CWU ");
|
||||
}
|
||||
}
|
||||
if (vfoActive == VFO_A) // VFO A is active
|
||||
strcat(c, "A:");
|
||||
else
|
||||
strcat(c, "B:");
|
||||
}
|
||||
|
||||
//Fixed by Mitani Massaru (JE4SMQ)
|
||||
if (isShiftDisplayCWFreq == 1)
|
||||
{
|
||||
if (cwMode == 1) //CWL
|
||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
||||
else if (cwMode == 2) //CWU
|
||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
||||
}
|
||||
|
||||
//display frequency
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) c[i] = '.';
|
||||
else {
|
||||
c[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
c[i] = ' ';
|
||||
}
|
||||
|
||||
//remarked by KD8CEC
|
||||
//already RX/TX status display, and over index (16 x 2 LCD)
|
||||
//if (inTx)
|
||||
// strcat(c, " TX");
|
||||
printLine(1, c);
|
||||
|
||||
byte diplayVFOLine = 1;
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayVFOLine = 0;
|
||||
|
||||
if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) ||
|
||||
(vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) {
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write((uint8_t)0);
|
||||
}
|
||||
else if (isCWAutoMode == 2){
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write(0x7E);
|
||||
}
|
||||
else
|
||||
{
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write(':');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char line2Buffer[16];
|
||||
//KD8CEC 200Hz ST
|
||||
//L14.150 200Hz ST
|
||||
//U14.150 +150khz
|
||||
int freqScrollPosition = 0;
|
||||
//Example Line2 Optinal Display
|
||||
//immediate execution, not call by scheulder
|
||||
void updateLine2Buffer(char displayType)
|
||||
{
|
||||
unsigned long tmpFreq = 0;
|
||||
if (ritOn)
|
||||
{
|
||||
strcpy(line2Buffer, "RitTX:");
|
||||
|
||||
//display frequency
|
||||
tmpFreq = ritTxFrequency;
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
return;
|
||||
} //end of ritOn display
|
||||
|
||||
//other VFO display
|
||||
if (vfoActive == VFO_B)
|
||||
{
|
||||
tmpFreq = vfoA;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpFreq = vfoB;
|
||||
}
|
||||
|
||||
// EXAMPLE 1 & 2
|
||||
//U14.150.100
|
||||
//display frequency
|
||||
for (int i = 9; i >= 0; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 2 || i == 6) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
//EXAMPLE #1
|
||||
if ((displayOption1 & 0x04) == 0x00) //none scroll display
|
||||
line2Buffer[6] = 'k';
|
||||
else
|
||||
{
|
||||
//example #2
|
||||
if (freqScrollPosition++ > 18) //none scroll display time
|
||||
{
|
||||
line2Buffer[6] = 'k';
|
||||
if (freqScrollPosition > 25)
|
||||
freqScrollPosition = -1;
|
||||
}
|
||||
else //scroll frequency
|
||||
{
|
||||
line2Buffer[10] = 'H';
|
||||
line2Buffer[11] = 'z';
|
||||
|
||||
if (freqScrollPosition < 7)
|
||||
{
|
||||
for (int i = 11; i >= 0; i--)
|
||||
if (i - (7 - freqScrollPosition) >= 0)
|
||||
line2Buffer[i] = line2Buffer[i - (7 - freqScrollPosition)];
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 11; i++)
|
||||
if (i + (freqScrollPosition - 7) <= 11)
|
||||
line2Buffer[i] = line2Buffer[i + (freqScrollPosition - 7)];
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
}
|
||||
} //scroll
|
||||
|
||||
line2Buffer[7] = ' ';
|
||||
|
||||
if (isIFShift)
|
||||
{
|
||||
// if (isDirectCall == 1)
|
||||
// for (int i = 0; i < 16; i++)
|
||||
// line2Buffer[i] = ' ';
|
||||
|
||||
//IFShift Offset Value
|
||||
line2Buffer[8] = 'I';
|
||||
line2Buffer[9] = 'F';
|
||||
|
||||
line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0;
|
||||
line2Buffer[11] = 0;
|
||||
line2Buffer[12] = ' ';
|
||||
|
||||
//11, 12, 13, 14, 15
|
||||
memset(b, 0, sizeof(b));
|
||||
ltoa(ifShiftValue, b, DEC);
|
||||
strncat(line2Buffer, b, 5);
|
||||
|
||||
//if (isDirectCall == 1) //if call by encoder (not scheduler), immediate print value
|
||||
printLine2(line2Buffer);
|
||||
} // end of display IF
|
||||
else // step & Key Type display
|
||||
{
|
||||
//if (isDirectCall != 0)
|
||||
// return;
|
||||
|
||||
memset(&line2Buffer[8], ' ', 8);
|
||||
//Step
|
||||
long tmpStep = arTuneStep[tuneStepIndex -1];
|
||||
|
||||
byte isStepKhz = 0;
|
||||
if (tmpStep >= 1000)
|
||||
{
|
||||
isStepKhz = 2;
|
||||
}
|
||||
|
||||
for (int i = 10; i >= 8 - isStepKhz; i--) {
|
||||
if (tmpStep > 0) {
|
||||
line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30;
|
||||
tmpStep /= 10;
|
||||
}
|
||||
else
|
||||
line2Buffer[i +isStepKhz] = ' ';
|
||||
}
|
||||
|
||||
if (isStepKhz == 0)
|
||||
{
|
||||
line2Buffer[11] = 'H';
|
||||
line2Buffer[12] = 'z';
|
||||
}
|
||||
|
||||
line2Buffer[13] = ' ';
|
||||
|
||||
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
||||
if (cwKeyType == 0)
|
||||
{
|
||||
line2Buffer[14] = 'S';
|
||||
line2Buffer[15] = 'T';
|
||||
}
|
||||
else if (cwKeyType == 1)
|
||||
{
|
||||
line2Buffer[14] = 'I';
|
||||
line2Buffer[15] = 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
line2Buffer[14] = 'I';
|
||||
line2Buffer[15] = 'B';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//meterType : 0 = S.Meter, 1 : P.Meter
|
||||
void DisplayMeter(byte meterType, byte meterValue, char drawPosition)
|
||||
{
|
||||
if (meterType == 0 || meterType == 1 || meterType == 2)
|
||||
{
|
||||
drawMeter(meterValue); //call original source code
|
||||
int lineNumber = 0;
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
lineNumber = 1;
|
||||
|
||||
LCD_SetCursor(drawPosition, lineNumber);
|
||||
|
||||
for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6
|
||||
LCD_Write(lcdMeter[i]);
|
||||
}
|
||||
}
|
||||
|
||||
byte testValue = 0;
|
||||
char checkCount = 0;
|
||||
void idle_process()
|
||||
{
|
||||
//space for user graphic display
|
||||
if (menuOn == 0)
|
||||
{
|
||||
if ((displayOption1 & 0x10) == 0x10) //always empty topline
|
||||
return;
|
||||
|
||||
//if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message
|
||||
if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) {
|
||||
if (checkCount++ > 1)
|
||||
{
|
||||
updateLine2Buffer(0); //call by scheduler
|
||||
printLine2(line2Buffer);
|
||||
line2DisplayStatus = 2;
|
||||
checkCount = 0;
|
||||
}
|
||||
|
||||
//EX for Meters
|
||||
/*
|
||||
DisplayMeter(0, testValue++, 7);
|
||||
if (testValue > 30)
|
||||
testValue = 0;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//AutoKey LCD Display Routine
|
||||
void Display_AutoKeyTextIndex(char textIndex)
|
||||
{
|
||||
byte diplayAutoCWLine = 0;
|
||||
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayAutoCWLine = 1;
|
||||
LCD_SetCursor(0, diplayAutoCWLine);
|
||||
LCD_Write(byteToChar(selectedCWTextIndex));
|
||||
LCD_Write(':');
|
||||
}
|
||||
|
||||
|
||||
#endif
|
22
ubitx_20/ubitx_lcd_2404i.ino
Normal file
22
ubitx_20/ubitx_lcd_2404i.ino
Normal file
@@ -0,0 +1,22 @@
|
||||
/*************************************************************************
|
||||
KD8CEC's uBITX Display Routine for LCD2404 I2C
|
||||
uBITX Idle time Processing
|
||||
Functions that run at times that do not affect TX, CW, and CAT
|
||||
It is called in 1/10 time unit.
|
||||
-----------------------------------------------------------------------------
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
22
ubitx_20/ubitx_lcd_2404p.ino
Normal file
22
ubitx_20/ubitx_lcd_2404p.ino
Normal file
@@ -0,0 +1,22 @@
|
||||
/*************************************************************************
|
||||
KD8CEC's uBITX Display Routine for LCD2404 Parrel
|
||||
uBITX Idle time Processing
|
||||
Functions that run at times that do not affect TX, CW, and CAT
|
||||
It is called in 1/10 time unit.
|
||||
-----------------------------------------------------------------------------
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,19 @@
|
||||
/************************************************************************************
|
||||
* KD8CEC
|
||||
* kd8cec@gmail.com http://www.hamskey.com
|
||||
*
|
||||
* Merge two SI5351 Librarys
|
||||
* KE7ER's fixed vco and variable Clocks Configure values
|
||||
* G3ZIL's fixed Clock Configure Value and variable VCO
|
||||
* * I have combined the two libraries above. All licenses follow the above library.
|
||||
*
|
||||
* PLL-A is generated by fixing 850Mhz clock. All output clocks use PLL-A to
|
||||
* generate the frequency. This is the method used in QRP radios such as uBITX.
|
||||
* When switching to WSPR transmission mode, PLL-B operates for the base frequency to transmit WSPR.
|
||||
* The output clock channel that controls the frequency is connected to the PLL-B.
|
||||
* The WSPR protocol is generated by changing the clock of the PLL-B.
|
||||
************************************************************************************/
|
||||
|
||||
// ************* SI5315 routines - tks Jerry Gaffke, KE7ER ***********************
|
||||
|
||||
// An minimalist standalone set of Si5351 routines.
|
||||
@@ -60,6 +76,7 @@ void i2cWriten(uint8_t reg, uint8_t *vals, uint8_t vcnt) { // write array
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t si5351Val[8] = {0, 1, 0, 0, 0, 0, 0, 0}; //for reduce program memory size
|
||||
|
||||
void si5351bx_init() { // Call once at power-up, start PLLA
|
||||
uint32_t msxp1;
|
||||
@@ -68,11 +85,13 @@ void si5351bx_init() { // Call once at power-up, start PLLA
|
||||
i2cWrite(3, si5351bx_clken); // Disable all CLK output drivers
|
||||
i2cWrite(183, SI5351BX_XTALPF << 6); // Set 25mhz crystal load capacitance
|
||||
msxp1 = 128 * SI5351BX_MSA - 512; // and msxp2=0, msxp3=1, not fractional
|
||||
uint8_t vals[8] = {0, 1, BB2(msxp1), BB1(msxp1), BB0(msxp1), 0, 0, 0};
|
||||
i2cWriten(26, vals, 8); // Write to 8 PLLA msynth regs
|
||||
//uint8_t vals[8] = {0, 1, BB2(msxp1), BB1(msxp1), BB0(msxp1), 0, 0, 0};
|
||||
si5351Val[2] = BB2(msxp1);
|
||||
si5351Val[3] = BB1(msxp1);
|
||||
si5351Val[4] = BB0(msxp1);
|
||||
|
||||
i2cWriten(26, si5351Val, 8); // Write to 8 PLLA msynth regs
|
||||
i2cWrite(177, 0x20); // Reset PLLA (0x80 resets PLLB)
|
||||
// for (reg=16; reg<=23; reg++) i2cWrite(reg, 0x80); // Powerdown CLK's
|
||||
// i2cWrite(187, 0); // No fannout of clkin, xtal, ms0, ms4
|
||||
}
|
||||
|
||||
void si5351bx_setfreq(uint8_t clknum, uint32_t fout) { // Set a CLK to fout Hz
|
||||
@@ -105,15 +124,48 @@ void si5351_set_calibration(int32_t cal){
|
||||
si5351bx_setfreq(0, usbCarrier);
|
||||
}
|
||||
|
||||
void SetCarrierFreq()
|
||||
{
|
||||
unsigned long appliedCarrier = ((cwMode == 0 ? usbCarrier : cwmCarrier) + (isIFShift && (inTx == 0) ? ifShiftValue : 0));
|
||||
si5351bx_setfreq(0, (sdrModeOn ? 0 : appliedCarrier));
|
||||
|
||||
/*
|
||||
if (cwMode == 0)
|
||||
si5351bx_setfreq(0, usbCarrier + (isIFShift ? ifShiftValue : 0));
|
||||
else
|
||||
si5351bx_setfreq(0, cwmCarrier + (isIFShift ? ifShiftValue : 0));
|
||||
*/
|
||||
}
|
||||
|
||||
void initOscillators(){
|
||||
//initialize the SI5351
|
||||
si5351bx_init();
|
||||
si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + calibration; // apply the calibration correction factor
|
||||
SetCarrierFreq();
|
||||
}
|
||||
|
||||
if (cwMode == 0)
|
||||
si5351bx_setfreq(0, usbCarrier);
|
||||
else
|
||||
si5351bx_setfreq(0, cwmCarrier);
|
||||
//============================================================
|
||||
// ADD FUNCTIONS by KD8CEC
|
||||
//============================================================
|
||||
uint8_t Wspr_Reg1[8] = {0xFF,0xFE, 0x00, 0, 0, 0, 0, 0}; //3, 4, 5, 6, 7
|
||||
uint8_t Wspr_Reg2[8] = {0, 1, 0, 0, 0, 0, 0, 0}; //2, 3, 4
|
||||
|
||||
void Set_WSPR_Param(void)
|
||||
{
|
||||
i2cWrite(18, 128);
|
||||
i2cWriten(34, Wspr_Reg1, 8);
|
||||
i2cWriten(58, Wspr_Reg2, 8);
|
||||
i2cWrite(177, 128);
|
||||
i2cWrite(18, 111);
|
||||
|
||||
si5351bx_clken &= ~(1 << 2);
|
||||
i2cWrite(3, si5351bx_clken);
|
||||
}
|
||||
|
||||
void TXSubFreq(unsigned long P2)
|
||||
{
|
||||
i2cWrite(40, (P2 & 65280) >> 8);
|
||||
i2cWrite(41, P2 & 255);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -5,310 +5,20 @@
|
||||
* of the radio. Occasionally, it is used to provide a two-line information that is
|
||||
* quickly cleared up.
|
||||
*/
|
||||
//#define printLineF1(x) (printLineF(1, x))
|
||||
//#define printLineF2(x) (printLineF(0, x))
|
||||
|
||||
//returns true if the button is pressed
|
||||
int btnDown(){
|
||||
if (digitalRead(FBUTTON) == HIGH)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Meter (not used in this build for anything)
|
||||
* the meter is drawn using special characters. Each character is composed of 5 x 8 matrix.
|
||||
* The s_meter array holds the definition of the these characters.
|
||||
* each line of the array is is one character such that 5 bits of every byte
|
||||
* makes up one line of pixels of the that character (only 5 bits are used)
|
||||
* The current reading of the meter is assembled in the string called meter
|
||||
*/
|
||||
|
||||
//char meter[17];
|
||||
|
||||
const PROGMEM uint8_t s_meter_bitmap[] = {
|
||||
B00000,B00000,B00000,B00000,B00000,B00100,B00100,B11011,
|
||||
B10000,B10000,B10000,B10000,B10100,B10100,B10100,B11011,
|
||||
B01000,B01000,B01000,B01000,B01100,B01100,B01100,B11011,
|
||||
B00100,B00100,B00100,B00100,B00100,B00100,B00100,B11011,
|
||||
B00010,B00010,B00010,B00010,B00110,B00110,B00110,B11011,
|
||||
B00001,B00001,B00001,B00001,B00101,B00101,B00101,B11011
|
||||
};
|
||||
PGM_P ps_meter_bitmap = reinterpret_cast<PGM_P>(s_meter_bitmap);
|
||||
|
||||
const PROGMEM uint8_t lock_bitmap[8] = {
|
||||
0b01110,
|
||||
0b10001,
|
||||
0b10001,
|
||||
0b11111,
|
||||
0b11011,
|
||||
0b11011,
|
||||
0b11111,
|
||||
0b00000};
|
||||
PGM_P plock_bitmap = reinterpret_cast<PGM_P>(lock_bitmap);
|
||||
|
||||
|
||||
// initializes the custom characters
|
||||
// we start from char 1 as char 0 terminates the string!
|
||||
void initMeter(){
|
||||
uint8_t tmpbytes[8];
|
||||
byte i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(plock_bitmap + i);
|
||||
lcd.createChar(0, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(ps_meter_bitmap + i);
|
||||
lcd.createChar(1, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(ps_meter_bitmap + i + 8);
|
||||
lcd.createChar(2, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(ps_meter_bitmap + i + 16);
|
||||
lcd.createChar(3, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(ps_meter_bitmap + i + 24);
|
||||
lcd.createChar(4, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(ps_meter_bitmap + i + 28);
|
||||
lcd.createChar(5, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(ps_meter_bitmap + i + 32);
|
||||
lcd.createChar(6, tmpbytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* The meter is drawn with special characters.
|
||||
* character 1 is used to simple draw the blocks of the scale of the meter
|
||||
* characters 2 to 6 are used to draw the needle in positions 1 to within the block
|
||||
* This displays a meter from 0 to 100, -1 displays nothing
|
||||
*/
|
||||
|
||||
/*
|
||||
void drawMeter(int8_t needle){
|
||||
int16_t best, i, s;
|
||||
|
||||
if (needle < 0)
|
||||
return;
|
||||
|
||||
s = (needle * 4)/10;
|
||||
for (i = 0; i < 8; i++){
|
||||
if (s >= 5)
|
||||
meter[i] = 1;
|
||||
else if (s >= 0)
|
||||
meter[i] = 2 + s;
|
||||
else
|
||||
meter[i] = 1;
|
||||
s = s - 5;
|
||||
}
|
||||
if (needle >= 40)
|
||||
meter[i-1] = 6;
|
||||
meter[i] = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// The generic routine to display one line on the LCD
|
||||
void printLine(unsigned char linenmbr, const char *c) {
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||
|
||||
if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change
|
||||
lcd.setCursor(0, linenmbr); // place the cursor at the beginning of the selected line
|
||||
lcd.print(c);
|
||||
strcpy(printBuff[linenmbr], c);
|
||||
|
||||
for (byte i = strlen(c); i < 16; i++) { // add white spaces until the end of the 16 characters line is reached
|
||||
lcd.print(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printLineF(char linenmbr, const __FlashStringHelper *c)
|
||||
{
|
||||
int i;
|
||||
char tmpBuff[17];
|
||||
PGM_P p = reinterpret_cast<PGM_P>(c);
|
||||
|
||||
for (i = 0; i < 17; i++){
|
||||
unsigned char fChar = pgm_read_byte(p++);
|
||||
tmpBuff[i] = fChar;
|
||||
if (fChar == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
printLine(linenmbr, tmpBuff);
|
||||
}
|
||||
|
||||
#define LCD_MAX_COLUMN 16
|
||||
void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex) {
|
||||
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(USER_CALLSIGN_DAT + i));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (byte i = lcdColumn; i < 16; i++) //Right Padding by Space
|
||||
lcd.write(' ');
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1(const char *c){
|
||||
printLine(1,c);
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2(const char *c){
|
||||
printLine(0,c);
|
||||
}
|
||||
|
||||
void clearLine2()
|
||||
{
|
||||
printLine2("");
|
||||
line2DisplayStatus = 0;
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1Clear(){
|
||||
printLine(1,"");
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2Clear(){
|
||||
printLine(0, "");
|
||||
}
|
||||
|
||||
void printLine2ClearAndUpdate(){
|
||||
printLine(0, "");
|
||||
line2DisplayStatus = 0;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
//012...89ABC...Z
|
||||
char byteToChar(byte srcByte){
|
||||
char byteToChar(byte srcByte){
|
||||
if (srcByte < 10)
|
||||
return 0x30 + srcByte;
|
||||
else
|
||||
return 'A' + srcByte - 10;
|
||||
}
|
||||
|
||||
// this builds up the top line of the display with frequency and mode
|
||||
void updateDisplay() {
|
||||
// tks Jack Purdum W8TEE
|
||||
// replaced fsprint commmands by str commands for code size reduction
|
||||
|
||||
// replace code for Frequency numbering error (alignment, point...) by KD8CEC
|
||||
int i;
|
||||
unsigned long tmpFreq = frequency; //
|
||||
|
||||
memset(c, 0, sizeof(c));
|
||||
|
||||
if (inTx){
|
||||
if (isCWAutoMode == 2) {
|
||||
for (i = 0; i < 4; i++)
|
||||
c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' ');
|
||||
|
||||
//display Sending Index
|
||||
c[4] = byteToChar(sendingCWTextIndex);
|
||||
c[5] = '=';
|
||||
}
|
||||
else {
|
||||
if (cwTimeout > 0)
|
||||
strcpy(c, " CW:");
|
||||
else
|
||||
strcpy(c, " TX:");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ritOn)
|
||||
strcpy(c, "RIT ");
|
||||
else {
|
||||
if (cwMode == 0)
|
||||
{
|
||||
if (isUSB)
|
||||
strcpy(c, "USB ");
|
||||
else
|
||||
strcpy(c, "LSB ");
|
||||
}
|
||||
else if (cwMode == 1)
|
||||
{
|
||||
strcpy(c, "CWL ");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(c, "CWU ");
|
||||
}
|
||||
}
|
||||
if (vfoActive == VFO_A) // VFO A is active
|
||||
strcat(c, "A:");
|
||||
else
|
||||
strcat(c, "B:");
|
||||
}
|
||||
|
||||
//display frequency
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) c[i] = '.';
|
||||
else {
|
||||
c[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
c[i] = ' ';
|
||||
}
|
||||
|
||||
//remarked by KD8CEC
|
||||
//already RX/TX status display, and over index (16 x 2 LCD)
|
||||
//if (inTx)
|
||||
// strcat(c, " TX");
|
||||
printLine(1, c);
|
||||
|
||||
byte diplayVFOLine = 1;
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayVFOLine = 0;
|
||||
|
||||
if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) ||
|
||||
(vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) {
|
||||
lcd.setCursor(5,diplayVFOLine);
|
||||
lcd.write((uint8_t)0);
|
||||
}
|
||||
else if (isCWAutoMode == 2){
|
||||
lcd.setCursor(5,diplayVFOLine);
|
||||
lcd.write(0x7E);
|
||||
}
|
||||
//returns true if the button is pressed
|
||||
int btnDown(void){
|
||||
if (digitalRead(FBUTTON) == HIGH)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
lcd.setCursor(5,diplayVFOLine);
|
||||
lcd.write(":");
|
||||
}
|
||||
|
||||
/*
|
||||
//now, the second line
|
||||
memset(c, 0, sizeof(c));
|
||||
memset(b, 0, sizeof(b));
|
||||
|
||||
if (inTx)
|
||||
strcat(c, "TX ");
|
||||
else if (ritOn)
|
||||
strcpy(c, "RIT");
|
||||
|
||||
strcpy(c, " \xff");
|
||||
drawMeter(meter_reading);
|
||||
strcat(c, meter);
|
||||
strcat(c, "\xff");
|
||||
printLine2(c);*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
int enc_prev_state = 3;
|
||||
|
193
ubitx_20/ubitx_wspr.ino
Normal file
193
ubitx_20/ubitx_wspr.ino
Normal file
@@ -0,0 +1,193 @@
|
||||
/**********************************************************************************
|
||||
WSPR SENDER for uBITX by KD8CEC
|
||||
Some of the code that sends WSPR referenced the code in G3ZIL.
|
||||
Thanks to G3ZIL for sharing great code.
|
||||
|
||||
Due to the limited memory of uBITX, I have implemented at least only a few of the codes in uBITX.
|
||||
|
||||
Thanks for testing
|
||||
Beta Tester :
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
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 <arduino.h>
|
||||
#include <EEPROM.h>
|
||||
#include "ubitx.h"
|
||||
|
||||
//begin of test
|
||||
byte WsprToneCode[164];
|
||||
|
||||
long lastTime=0;
|
||||
unsigned long TX_MSNB_P2; // Si5351 register MSNB_P2 PLLB for Tx
|
||||
unsigned long TX_P2; // Variable values for MSNB_P2 which defines the frequencies for the data
|
||||
|
||||
extern int enc_read(void);
|
||||
|
||||
byte WsprMSGCount = 0;
|
||||
#define PTT (A3)
|
||||
|
||||
#define WSPR_BAND1 401
|
||||
|
||||
extern uint8_t Wspr_Reg1[8]; //3, 4, 5, 6, 7
|
||||
extern uint8_t Wspr_Reg2[8]; //2, 3, 4
|
||||
|
||||
void SendWSPRManage()
|
||||
{
|
||||
int knob = 0;
|
||||
byte knobPosition = 0;
|
||||
char isNeedDisplayInfo = 0;
|
||||
char nowSelectedIndex = 0;
|
||||
char nowWsprStep = 0; //0 : select Message, 1 : select band, 2 : send
|
||||
char selectedWsprMessageIndex = -1;
|
||||
char selectedWsprBandIndex = -1;
|
||||
|
||||
unsigned long WsprTXFreq = 0;
|
||||
unsigned int WsprMultiChan = 0;
|
||||
unsigned long prevFreq;
|
||||
char loopIndex;
|
||||
|
||||
delay_background(500, 0);
|
||||
|
||||
//Readed WsprMSGCount, WsprTone
|
||||
while(1)
|
||||
{
|
||||
knob = enc_read();
|
||||
|
||||
if (knobPosition > 0 && knob < 0)
|
||||
knobPosition--;
|
||||
else if (knob > 0 && (knobPosition <= (nowWsprStep == 0 ? WsprMSGCount : WSPR_BAND_COUNT) * 10 -2))
|
||||
knobPosition++;
|
||||
|
||||
nowSelectedIndex = knobPosition / 10;
|
||||
|
||||
if (nowWsprStep == 0) //select Message status
|
||||
{
|
||||
printLineF2(F("WSPR:"));
|
||||
|
||||
if (selectedWsprMessageIndex != nowSelectedIndex)
|
||||
{
|
||||
selectedWsprMessageIndex = nowSelectedIndex;
|
||||
int wsprMessageBuffIndex = selectedWsprMessageIndex * 46;
|
||||
|
||||
//Display WSPR Name tag
|
||||
printLineFromEEPRom(0, 6, wsprMessageBuffIndex, wsprMessageBuffIndex + 4, 1);
|
||||
|
||||
//Load WSPR Tonecode
|
||||
//Read Tone Code
|
||||
for (int i = 0; i < 41; i++)
|
||||
{
|
||||
byte readData = EEPROM.read(WSPR_MESSAGE1 + 5 + (wsprMessageBuffIndex) + i); //NAME TAG 5, MESSAGE 41 = 46
|
||||
WsprToneCode[i * 4 + 0] = readData & 3;
|
||||
WsprToneCode[i * 4 + 1] = (readData >> 2) & 3;
|
||||
WsprToneCode[i * 4 + 2] = (readData >> 4) & 3;
|
||||
WsprToneCode[i * 4 + 3] = (readData >> 6) & 3;
|
||||
}
|
||||
}
|
||||
else if (btnDown())
|
||||
{
|
||||
nowWsprStep = 1; //Change Status to Select Band
|
||||
knobPosition = 0;
|
||||
nowSelectedIndex = 0;
|
||||
delay_background(500, 0);
|
||||
}
|
||||
}
|
||||
else if (nowWsprStep == 1)
|
||||
{
|
||||
//printLineF2(F("Select Band"));
|
||||
if (selectedWsprBandIndex != nowSelectedIndex)
|
||||
{
|
||||
selectedWsprBandIndex = nowSelectedIndex;
|
||||
int bandBuffIndex = WSPR_BAND1 + selectedWsprBandIndex * 14;
|
||||
|
||||
EEPROM.get(bandBuffIndex, WsprTXFreq);
|
||||
EEPROM.get(bandBuffIndex + 4, WsprMultiChan);
|
||||
|
||||
/*
|
||||
//3, 4, 5, 6, 7
|
||||
Wspr_Reg1[3] = EEPROM.read(bandBuffIndex + 6);
|
||||
Wspr_Reg1[4] = EEPROM.read(bandBuffIndex + 7);
|
||||
Wspr_Reg1[5] = EEPROM.read(bandBuffIndex + 8);
|
||||
Wspr_Reg1[6] = EEPROM.read(bandBuffIndex + 9);
|
||||
Wspr_Reg1[7] = EEPROM.read(bandBuffIndex + 10);
|
||||
*/
|
||||
for (loopIndex = 3; loopIndex < 8; loopIndex++)
|
||||
Wspr_Reg1[loopIndex] = EEPROM.read(bandBuffIndex + loopIndex + 3);
|
||||
|
||||
/*
|
||||
Wspr_Reg2[2] = EEPROM.read(bandBuffIndex + 11);
|
||||
Wspr_Reg2[3] = EEPROM.read(bandBuffIndex + 12);
|
||||
Wspr_Reg2[4] = EEPROM.read(bandBuffIndex + 13);
|
||||
*/
|
||||
//2, 3, 4
|
||||
for (loopIndex = 2; loopIndex < 5; loopIndex++)
|
||||
Wspr_Reg2[loopIndex] = EEPROM.read(bandBuffIndex + loopIndex + 9);
|
||||
|
||||
TX_MSNB_P2 = ((unsigned long)Wspr_Reg1[5] & 0x0F) << 16 | ((unsigned long)Wspr_Reg1[6]) << 8 | Wspr_Reg1[7];
|
||||
}
|
||||
|
||||
ltoa(WsprTXFreq, b, DEC);
|
||||
if (digitalRead(PTT) == 0)
|
||||
strcpy(c, "SEND:");
|
||||
else
|
||||
strcpy(c, "PTT->");
|
||||
|
||||
strcat(c, b);
|
||||
printLine1(c);
|
||||
|
||||
if (digitalRead(PTT) == 0)
|
||||
{
|
||||
//printLineF1(F("Transmitting"));
|
||||
//SEND WSPR
|
||||
//If you need to consider the Rit and Sprite modes, uncomment them below.
|
||||
//remark = To reduce the size of the program
|
||||
//prevFreq = frequency;
|
||||
//frequency = WsprTXFreq;
|
||||
startTx(TX_CW, 0);
|
||||
setTXFilters(WsprTXFreq);
|
||||
|
||||
//Start WSPR
|
||||
Set_WSPR_Param();
|
||||
digitalWrite(CW_KEY, 1);
|
||||
|
||||
for (int i = 0; i < 162; i++)
|
||||
{ // Now this is the message loop
|
||||
lastTime = millis(); // Store away the time when the last message symbol was sent
|
||||
TX_P2 = TX_MSNB_P2 + WsprMultiChan * WsprToneCode[i]; // This represents the 1.46 Hz shift and is correct only for the bands specified in the array
|
||||
TXSubFreq(TX_P2); // TX at the appropriate channel frequency for....
|
||||
|
||||
//if (btnDown())
|
||||
// break;
|
||||
|
||||
while (millis() < lastTime + 683){} // .... 0,683 seconds
|
||||
}
|
||||
|
||||
digitalWrite(CW_KEY, 0);
|
||||
stopTx(); //call setFrequency -> recovery TX Filter
|
||||
//frequency = prevFreq;
|
||||
|
||||
selectedWsprBandIndex = -1;
|
||||
} //end of PTT Check
|
||||
else if (btnDown())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
} //end of status check
|
||||
|
||||
//delay_background(50, 1);
|
||||
} //end of while
|
||||
}
|
||||
|
BIN
ubitxmanager ubuntu.odt
Normal file
BIN
ubitxmanager ubuntu.odt
Normal file
Binary file not shown.
Reference in New Issue
Block a user