Compare commits
64 Commits
cwtone-cfg
...
v0.33
Author | SHA1 | Date | |
---|---|---|---|
|
4f5ac283b7 | ||
|
4745790dfa | ||
|
85832de034 | ||
|
4830db78cb | ||
|
5eca64d2a9 | ||
|
0d9ec08bd7 | ||
|
3058d52551 | ||
|
98c26730c6 | ||
|
3a306429ea | ||
|
4f634a8277 | ||
|
a49d5e85b8 | ||
|
04699ba074 | ||
|
282c196f63 | ||
|
aa61281c38 | ||
|
ee23827def | ||
|
261215b1ad | ||
|
1a2f5b4fde | ||
|
8d4c788e11 | ||
|
cc7dd752e6 | ||
|
4506ff1c1b | ||
|
8203427808 | ||
|
db543c43e1 | ||
|
4e15f2150c | ||
|
82a5fd7df9 | ||
|
981db341db | ||
|
020b34e504 | ||
|
386a0b2d46 | ||
|
c6401af7d1 | ||
|
b153a305d6 | ||
|
c7be3dcd39 | ||
|
bbb23bf817 | ||
|
4d61cf4de9 | ||
|
e61e45d3dd | ||
|
a1f941f965 | ||
|
d1e72b3bd5 | ||
|
032e7f919f | ||
|
b6bc264332 | ||
|
b1cc5eb98a | ||
|
2fa8247501 | ||
|
2fe1662d67 | ||
|
ebbc5aae5e | ||
|
209cd3a49c | ||
|
587d4854c3 | ||
|
95e5c1dfe5 | ||
|
45a8479061 | ||
|
a6ad381c24 | ||
|
bcf80f851d | ||
|
16304efacd | ||
|
968024ab73 | ||
|
3e60728727 | ||
|
924db221f4 | ||
|
b9b8f4b46f | ||
|
9781ef086b | ||
|
f27f504ea4 | ||
|
b2d3e3a6f8 | ||
|
2b08a76fbf | ||
|
f9050ebb11 | ||
|
90655e03b8 | ||
|
8551ff1b68 | ||
|
5ce94e8e49 | ||
|
7ef9c29fa8 | ||
|
fda398046e | ||
|
f563e74a4e | ||
|
8176b50f48 |
133
README.md
133
README.md
@@ -1,4 +1,137 @@
|
|||||||
|
#IMPORTANT INFORMATION
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
- 0.30 Version Test only download. almost complete
|
||||||
|
- Beta 0.26 and Beta 0.261, Beta 0.262,0.27 is complete test, 0.28 is tested.
|
||||||
|
- You can download and use it (Release section).
|
||||||
|
|
||||||
|
# Current work list (for Version 0.31)
|
||||||
|
1 Testing CAT Control with Software using hamlib on Linux
|
||||||
|
|
||||||
|
#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
|
||||||
|
kd8cec@gmail.com
|
||||||
|
|
||||||
|
#uBITX
|
||||||
|
uBITX firmware, written for the Raduino/Arduino control of uBITX transceivers
|
||||||
|
This project is based on https://github.com/afarhan/ubitx and all copyright is inherited.
|
||||||
|
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
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
## REVISION RECORD
|
||||||
|
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)
|
||||||
|
- Support Ham band on uBITX
|
||||||
|
default Hamband is regeion1 but customize by uBITX Manager Software
|
||||||
|
- Advanced ham band options (Tx control) for use in all countries. You can adjust it yourself.
|
||||||
|
- Convenience of band movement
|
||||||
|
|
||||||
|
0.26
|
||||||
|
- only Beta tester released & source code share
|
||||||
|
- find a bug on none initial eeprom uBITX - Fixed (Check -> initialized & compatible original source code)
|
||||||
|
- change the version number 0.26 -> 0.27
|
||||||
|
- Prevent overflow bugs
|
||||||
|
- bug with linux based Hamlib (raspberry pi), It was perfect for the 0.224 version, but there was a problem for the 0.25 version.
|
||||||
|
On Windows, ham deluxe, wsjt-x, jt65-hf, and fldigi were successfully run. Problem with Raspberry pi.
|
||||||
|
|
||||||
|
0.25
|
||||||
|
- Beta Version Released
|
||||||
|
http://www.hamskey.com/2018/01/release-beta-version-of-cat-support.html
|
||||||
|
- Added CAT Protocol for uBITX
|
||||||
|
- Modified the default usb carrier value used when the setting is wrong.
|
||||||
|
- Fixed a routine to repair when the CAT protocol was interrupted.
|
||||||
|
|
||||||
|
0.24
|
||||||
|
- Program optimization
|
||||||
|
reduce usage ram rate (string with M() optins)
|
||||||
|
- Optimized CAT protocol for wsjt-x, fldigi
|
||||||
|
|
||||||
|
0.23
|
||||||
|
- added delay_background() , replace almost delay() to delay_background for prevent timeout
|
||||||
|
- cat library compatible with FT-817 Command
|
||||||
|
switch VFOA / VFOB,
|
||||||
|
Read Write CW Speed
|
||||||
|
Read Write CW Delay Time
|
||||||
|
Read Write CW Pitch (with sidetone)
|
||||||
|
All of these can be controlled by Hamradio deluxe.
|
||||||
|
|
||||||
|
- modified cat libray function for protocol for CAT communication is not broken in CW or TX mode
|
||||||
|
- Ability to change CW Delay
|
||||||
|
- Added Dial Lock function
|
||||||
|
- Add functions CW Start dely (TX -> CW interval)
|
||||||
|
- Automatic storage of VFO frequency
|
||||||
|
It was implemented by storing it only once when the frequency stays 10 seconds or more after the change.
|
||||||
|
(protect eeprom life)
|
||||||
|
|
||||||
|
|
||||||
|
0.22
|
||||||
|
- fixed screen Update Problem
|
||||||
|
- Frequency Display Problem - Problems occur below 1Mhz
|
||||||
|
- added function Enhanced CAT communication
|
||||||
|
- replace ubitx_cat.ino to cat_libs.ino
|
||||||
|
- Save mode when switching to VFOA / VFOB
|
||||||
|
|
||||||
|
|
||||||
|
0.21
|
||||||
|
- fixed the cw side tone configuration.
|
||||||
|
- Fix the error that the frequency is over.
|
||||||
|
- fixed frequency display (alignment, point)
|
||||||
|
|
||||||
|
|
||||||
|
0.20
|
||||||
|
- original uBITX software (Ashhar Farhan)
|
||||||
|
|
||||||
|
## Original README.md
|
||||||
uBITX firmware, written for the Raduino/Arduino control of uBITX transceigers
|
uBITX firmware, written for the Raduino/Arduino control of uBITX transceigers
|
||||||
|
|
||||||
Copyright (C) 2017, Ashhar Farhan
|
Copyright (C) 2017, Ashhar Farhan
|
||||||
|
783
ubitx_20/cat_libs.ino
Normal file
783
ubitx_20/cat_libs.ino
Normal file
@@ -0,0 +1,783 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
KD8CEC's CAT Library for uBITX and HAM
|
||||||
|
This source code is written for uBITX, but it can also be used on other radios.
|
||||||
|
|
||||||
|
The CAT protocol is used by many radios to provide remote control to comptuers through
|
||||||
|
the serial port.
|
||||||
|
it is based on FT-817, uBITX's only protocol has been added and will be added in the future.
|
||||||
|
In addition, simple things such as FT-857 frequency control and PTT control can also be
|
||||||
|
transmitted to the FT-857 protocol.
|
||||||
|
|
||||||
|
This code refers to the following code.
|
||||||
|
- FT857D CAT Library, by Pavel Milanes, CO7WT, pavelmc@gmail.com
|
||||||
|
https://github.com/pavelmc/FT857d/
|
||||||
|
- Ham Radio Control Libraries, https://sourceforge.net/projects/hamlib/
|
||||||
|
- Not found protocols decription were analyzed using an RS-232 analyzer.
|
||||||
|
using FT-817 and
|
||||||
|
- http://www.ka7oei.com/ft817_meow.html <-- It was a great help here.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
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 printLineF1(x) (printLineF(1, x))
|
||||||
|
#define printLineF2(x) (printLineF(0, x))
|
||||||
|
|
||||||
|
//for broken protocol
|
||||||
|
#define CAT_RECEIVE_TIMEOUT 500
|
||||||
|
|
||||||
|
#define CAT_MODE_LSB 0x00
|
||||||
|
#define CAT_MODE_USB 0x01
|
||||||
|
#define CAT_MODE_CW 0x02
|
||||||
|
#define CAT_MODE_CWR 0x03
|
||||||
|
#define CAT_MODE_AM 0x04
|
||||||
|
#define CAT_MODE_FM 0x08
|
||||||
|
#define CAT_MODE_DIG 0x0A
|
||||||
|
#define CAT_MODE_PKT 0x0C
|
||||||
|
#define CAT_MODE_FMN 0x88
|
||||||
|
|
||||||
|
#define ACK 0
|
||||||
|
|
||||||
|
unsigned int skipTimeCount = 0;
|
||||||
|
byte CAT_BUFF[5];
|
||||||
|
byte CAT_SNDBUFF[5];
|
||||||
|
|
||||||
|
void SendCatData(byte sendCount)
|
||||||
|
{
|
||||||
|
for (byte i = 0; i < sendCount; i++)
|
||||||
|
Serial.write(CAT_BUFF[i]);
|
||||||
|
//Serial.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
//PROTOCOL : 0x01
|
||||||
|
//Computer ->(frequency)-> TRCV CAT_BUFF
|
||||||
|
void CatSetFreq(byte fromType)
|
||||||
|
{
|
||||||
|
//CAT_BUFF
|
||||||
|
byte i;
|
||||||
|
unsigned long tempFreq = 0;
|
||||||
|
|
||||||
|
if (fromType == 2 || fromType == 3) {
|
||||||
|
Serial.write(ACK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//2 digit in 1 byte (4 bit + 4bit) * 4.5 byte
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
tempFreq *= 10;
|
||||||
|
tempFreq += CAT_BUFF[i] >> 4;
|
||||||
|
tempFreq *= 10;
|
||||||
|
tempFreq += CAT_BUFF[i] & 0x0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempFreq *= 10;
|
||||||
|
tempFreq += CAT_BUFF[4] >> 4;
|
||||||
|
|
||||||
|
if (!inTx && (frequency != tempFreq))
|
||||||
|
{
|
||||||
|
//Check Frequency Range
|
||||||
|
if (tempFreq >= LOWEST_FREQ_DIAL && tempFreq <= HIGHEST_FREQ_DIAL)
|
||||||
|
{
|
||||||
|
setFrequency(tempFreq);
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//KD8CEC
|
||||||
|
//Remark for rduce program size, if you need, you can remove remark,
|
||||||
|
//however alomost rig control software available 1.0 ~ 50Mhz
|
||||||
|
//printLine(0, "OUT OF RANGE!!!");
|
||||||
|
//delay_background(300, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.write(ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
//#define BCD_LEN 9
|
||||||
|
//PROTOCOL : 0x03
|
||||||
|
//Computer <-(frequency)-> TRCV CAT_BUFF
|
||||||
|
void CatGetFreqMode(unsigned long freq, byte fromType)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
byte tmpValue;
|
||||||
|
unsigned BCD_LEN = 9;
|
||||||
|
|
||||||
|
if (BCD_LEN & 1) {
|
||||||
|
CAT_BUFF[BCD_LEN / 2] &= 0x0f;
|
||||||
|
CAT_BUFF[BCD_LEN / 2] |= (freq % 10) << 4;
|
||||||
|
|
||||||
|
freq /= 10;
|
||||||
|
}
|
||||||
|
for (i = (BCD_LEN / 2) - 1; i >= 0; i--) {
|
||||||
|
tmpValue = freq % 10;
|
||||||
|
freq /= 10;
|
||||||
|
tmpValue |= (freq % 10) << 4;
|
||||||
|
freq /= 10;
|
||||||
|
CAT_BUFF[i] = tmpValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Mode Check
|
||||||
|
if (cwMode == 0)
|
||||||
|
{
|
||||||
|
if (isUSB)
|
||||||
|
CAT_BUFF[4] = CAT_MODE_USB;
|
||||||
|
else
|
||||||
|
CAT_BUFF[4] = CAT_MODE_LSB;
|
||||||
|
}
|
||||||
|
else if (cwMode == 1)
|
||||||
|
{
|
||||||
|
CAT_BUFF[4] = CAT_MODE_CW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CAT_BUFF[4] = CAT_MODE_CW;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendCatData(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CatSetSplit(boolean isSplit, byte fromType)
|
||||||
|
{
|
||||||
|
|
||||||
|
Serial.write(ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CatSetPTT(boolean isPTTOn, byte fromType)
|
||||||
|
{
|
||||||
|
if (fromType == 2 || fromType == 3) {
|
||||||
|
Serial.write(ACK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set PTT Mode
|
||||||
|
if (isPTTOn)
|
||||||
|
{
|
||||||
|
if (!inTx)
|
||||||
|
{
|
||||||
|
txCAT = true;
|
||||||
|
|
||||||
|
startTx(TX_SSB, 1);
|
||||||
|
//Exit menu, Memory Keyer... ETC
|
||||||
|
if (isCWAutoMode > 0) {
|
||||||
|
isCWAutoMode = 0;
|
||||||
|
printLineF2(F("AutoKey Exit/CAT"));
|
||||||
|
//delay_background(1000, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (inTx)
|
||||||
|
{
|
||||||
|
stopTx();
|
||||||
|
txCAT = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.write(ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CatVFOToggle(boolean isSendACK, byte fromType)
|
||||||
|
{
|
||||||
|
if (fromType != 2 && fromType != 3) {
|
||||||
|
menuVfoToggle(1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSendACK)
|
||||||
|
Serial.write(ACK); //Time
|
||||||
|
}
|
||||||
|
|
||||||
|
void CatSetMode(byte tmpMode, byte fromType)
|
||||||
|
{
|
||||||
|
if (fromType == 2 || fromType == 3) {
|
||||||
|
Serial.write(ACK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inTx)
|
||||||
|
{
|
||||||
|
if (tmpMode == CAT_MODE_CW)
|
||||||
|
{
|
||||||
|
cwMode = 1;
|
||||||
|
}
|
||||||
|
else if (tmpMode == CAT_MODE_USB)
|
||||||
|
{
|
||||||
|
cwMode = 0;
|
||||||
|
isUSB = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cwMode = 0;
|
||||||
|
isUSB = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFrequency(frequency);
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.write(ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read EEProm by uBITX Manager Software
|
||||||
|
void ReadEEPRom(byte fromType)
|
||||||
|
{
|
||||||
|
//5BYTES
|
||||||
|
//CAT_BUFF[0] [1] [2] [3] [4] //4 COMMAND
|
||||||
|
//0, 1 START ADDRESS
|
||||||
|
uint16_t eepromStartIndex = CAT_BUFF[0] + CAT_BUFF[1] * 256;
|
||||||
|
uint16_t eepromReadLength = CAT_BUFF[2] + CAT_BUFF[3] * 256;;
|
||||||
|
byte checkSum = 0;
|
||||||
|
byte read1Byte = 0;
|
||||||
|
|
||||||
|
Serial.write(0x02); //STX
|
||||||
|
checkSum = 0x02;
|
||||||
|
for (uint16_t i = 0; i < eepromReadLength; i++)
|
||||||
|
{
|
||||||
|
read1Byte = EEPROM.read(eepromStartIndex + i);
|
||||||
|
checkSum += read1Byte;
|
||||||
|
Serial.write(read1Byte);
|
||||||
|
}
|
||||||
|
Serial.write(checkSum);
|
||||||
|
Serial.write(ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Write just proecess 1byes
|
||||||
|
void WriteEEPRom(byte fromType)
|
||||||
|
{
|
||||||
|
//5BYTES
|
||||||
|
uint16_t eepromStartIndex = CAT_BUFF[0] + CAT_BUFF[1] * 256;
|
||||||
|
byte write1Byte = CAT_BUFF[2];
|
||||||
|
|
||||||
|
//Check Checksum
|
||||||
|
if (CAT_BUFF[3] != ((CAT_BUFF[0] + CAT_BUFF[1] + CAT_BUFF[2]) % 256))
|
||||||
|
{
|
||||||
|
Serial.write(0x56); //CHECK SUM ERROR
|
||||||
|
Serial.write(ACK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EEPROM.write(eepromStartIndex, write1Byte);
|
||||||
|
Serial.write(0x77); //OK
|
||||||
|
Serial.write(ACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadEEPRom_FT817(byte fromType)
|
||||||
|
{
|
||||||
|
byte temp0 = CAT_BUFF[0];
|
||||||
|
byte temp1 = CAT_BUFF[1];
|
||||||
|
|
||||||
|
CAT_BUFF[0] = 0;
|
||||||
|
CAT_BUFF[1] = 0;
|
||||||
|
|
||||||
|
switch (temp1)
|
||||||
|
{
|
||||||
|
case 0x45 : //
|
||||||
|
if (temp0 == 0x03)
|
||||||
|
{
|
||||||
|
CAT_BUFF[0] = 0x00;
|
||||||
|
CAT_BUFF[1] = 0xD0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x47 : //
|
||||||
|
if (temp0 == 0x03)
|
||||||
|
{
|
||||||
|
CAT_BUFF[0] = 0xDC;
|
||||||
|
CAT_BUFF[1] = 0xE0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x55 :
|
||||||
|
//0 : VFO A/B 0 = VFO-A, 1 = VFO-B
|
||||||
|
//1 : MTQMB Select 0 = (Not MTQMB), 1 = MTQMB ("Memory Tune Quick Memory Bank")
|
||||||
|
//2 : QMB Select 0 = (Not QMB), 1 = QMB ("Quick Memory Bank")
|
||||||
|
//3 :
|
||||||
|
//4 : Home Select 0 = (Not HOME), 1 = HOME memory
|
||||||
|
//5 : Memory/MTUNE select 0 = Memory, 1 = MTUNE
|
||||||
|
//6 :
|
||||||
|
//7 : MEM/VFO Select 0 = Memory, 1 = VFO (A or B - see bit 0)
|
||||||
|
CAT_BUFF[0] = 0x80 + (vfoActive == VFO_B ? 1 : 0);
|
||||||
|
CAT_BUFF[1] = 0x00;
|
||||||
|
break;
|
||||||
|
case 0x57 : //
|
||||||
|
//0 : 1-0 AGC Mode 00 = Auto, 01 = Fast, 10 = Slow, 11 = Off
|
||||||
|
//2 DSP On/Off 0 = Off, 1 = On (Display format)
|
||||||
|
//4 PBT On/Off 0 = Off, 1 = On (Passband Tuning)
|
||||||
|
//5 NB On/Off 0 = Off, 1 = On (Noise Blanker)
|
||||||
|
//6 Lock On/Off 0 = Off, 1 = On (Dial Lock)
|
||||||
|
//7 FST (Fast Tuning) On/Off 0 = Off, 1 = On (Fast tuning)
|
||||||
|
|
||||||
|
CAT_BUFF[0] = 0xC0;
|
||||||
|
CAT_BUFF[1] = 0x40;
|
||||||
|
break;
|
||||||
|
case 0x59 : // band select VFO A Band Select 0000 = 160 M, 0001 = 75 M, 0010 = 40 M, 0011 = 30 M, 0100 = 20 M, 0101 = 17 M, 0110 = 15 M, 0111 = 12 M, 1000 = 10 M, 1001 = 6 M, 1010 = FM BCB, 1011 = Air, 1100 = 2 M, 1101 = UHF, 1110 = (Phantom)
|
||||||
|
//http://www.ka7oei.com/ft817_memmap.html
|
||||||
|
//CAT_BUFF[0] = 0xC2;
|
||||||
|
//CAT_BUFF[1] = 0x82;
|
||||||
|
break;
|
||||||
|
case 0x5C : //Beep Volume (0-100) (#13)
|
||||||
|
CAT_BUFF[0] = 0xB2;
|
||||||
|
CAT_BUFF[1] = 0x42;
|
||||||
|
break;
|
||||||
|
case 0x5E :
|
||||||
|
//3-0 : CW Pitch (300-1000 Hz) (#20) From 0 to E (HEX) with 0 = 300 Hz and each step representing 50 Hz
|
||||||
|
//5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel
|
||||||
|
//7-6 : Op Filter (#38) 00 = Off, 01 = SSB, 10 = CW
|
||||||
|
//CAT_BUFF[0] = 0x08;
|
||||||
|
CAT_BUFF[0] = sideTonePitch;
|
||||||
|
CAT_BUFF[1] = 0x25;
|
||||||
|
break;
|
||||||
|
case 0x61 : //Sidetone (Volume) (#44)
|
||||||
|
CAT_BUFF[0] = sideToneSub;
|
||||||
|
CAT_BUFF[1] = 0x08;
|
||||||
|
break;
|
||||||
|
case 0x5F : //
|
||||||
|
//4-0 CW Weight (1.:2.5-1:4.5) (#22) From 0 to 14 (HEX) with 0 = 1:2.5, incrementing in 0.1 weight steps
|
||||||
|
//5 420 ARS (#2) 0 = Off, 1 = On
|
||||||
|
//6 144 ARS (#1) 0 = Off, 1 = On
|
||||||
|
//7 Sql/RF-G (#45) 0 = Off, 1 = On
|
||||||
|
CAT_BUFF[0] = 0x32;
|
||||||
|
CAT_BUFF[1] = 0x08;
|
||||||
|
break;
|
||||||
|
case 0x60 : //CW Delay (10-2500 ms) (#17) From 1 to 250 (decimal) with each step representing 10 ms
|
||||||
|
CAT_BUFF[0] = cwDelayTime;
|
||||||
|
CAT_BUFF[1] = 0x32;
|
||||||
|
break;
|
||||||
|
case 0x62 : //
|
||||||
|
//5-0 CW Speed (4-60 WPM) (#21) From 0 to 38 (HEX) with 0 = 4 WPM and 38 = 60 WPM (1 WPM steps)
|
||||||
|
//7-6 Batt-Chg (6/8/10 Hours (#11) 00 = 6 Hours, 01 = 8 Hours, 10 = 10 Hours
|
||||||
|
//CAT_BUFF[0] = 0x08;
|
||||||
|
CAT_BUFF[0] = 1200 / cwSpeed - 4;
|
||||||
|
CAT_BUFF[1] = 0xB2;
|
||||||
|
break;
|
||||||
|
case 0x63 : //
|
||||||
|
//6-0 VOX Gain (#51) Contains 1-100 (decimal) as displayed
|
||||||
|
//7 Disable AM/FM Dial (#4) 0 = Enable, 1 = Disable
|
||||||
|
CAT_BUFF[0] = 0xB2;
|
||||||
|
CAT_BUFF[1] = 0xA5;
|
||||||
|
break;
|
||||||
|
case 0x64 : //
|
||||||
|
break;
|
||||||
|
case 0x67 : //6-0 SSB Mic (#46) Contains 0-100 (decimal) as displayed
|
||||||
|
CAT_BUFF[0] = 0xB2;
|
||||||
|
CAT_BUFF[1] = 0xB2;
|
||||||
|
break; case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed
|
||||||
|
case 0x78 :
|
||||||
|
if (cwMode == 0)
|
||||||
|
{
|
||||||
|
if (isUSB)
|
||||||
|
CAT_BUFF[0] = CAT_MODE_USB;
|
||||||
|
else
|
||||||
|
CAT_BUFF[0] = CAT_MODE_LSB;
|
||||||
|
}
|
||||||
|
else if (cwMode == 1)
|
||||||
|
{
|
||||||
|
CAT_BUFF[0] = CAT_MODE_CW;
|
||||||
|
}
|
||||||
|
else if (cwMode == 2)
|
||||||
|
{
|
||||||
|
CAT_BUFF[0] = CAT_MODE_CW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CAT_BUFF[0] != 0) CAT_BUFF[0] = 1 << 5;
|
||||||
|
break;
|
||||||
|
case 0x79 : //
|
||||||
|
//1-0 TX Power (All bands) 00 = High, 01 = L3, 10 = L2, 11 = L1
|
||||||
|
//3 PRI On/Off 0 = Off, 1 = On
|
||||||
|
//DW On/Off 0 = Off, 1 = On
|
||||||
|
//SCN (Scan) Mode 00 = No scan, 10 = Scan up, 11 = Scan down
|
||||||
|
//ART On/Off 0 = Off, 1 = On
|
||||||
|
CAT_BUFF[0] = 0x00;
|
||||||
|
CAT_BUFF[1] = 0x00;
|
||||||
|
break;
|
||||||
|
case 0x7A : //SPLIT
|
||||||
|
//7A 0 HF Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 1 6 M Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 2 FM BCB Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 3 Air Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 4 2 M Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 5 UHF Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 6 ? ?
|
||||||
|
//7A 7 SPL On/Off 0 = Off, 1 = On
|
||||||
|
|
||||||
|
CAT_BUFF[0] = (splitOn ? 0xFF : 0x7F);
|
||||||
|
break;
|
||||||
|
case 0xB3 : //
|
||||||
|
CAT_BUFF[0] = 0x00;
|
||||||
|
CAT_BUFF[1] = 0x4D;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// sent the data
|
||||||
|
SendCatData(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteEEPRom_FT817(byte fromType)
|
||||||
|
{
|
||||||
|
//byte temp0 = CAT_BUFF[0];
|
||||||
|
byte temp1 = CAT_BUFF[1];
|
||||||
|
|
||||||
|
CAT_BUFF[0] = 0;
|
||||||
|
CAT_BUFF[1] = 0;
|
||||||
|
|
||||||
|
if (fromType == 2 || fromType == 3) {
|
||||||
|
SendCatData(2);
|
||||||
|
Serial.write(ACK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (temp1)
|
||||||
|
{
|
||||||
|
case 0x55 :
|
||||||
|
//0 : VFO A/B 0 = VFO-A, 1 = VFO-B
|
||||||
|
//1 : MTQMB Select 0 = (Not MTQMB), 1 = MTQMB ("Memory Tune Quick Memory Bank")
|
||||||
|
//2 : QMB Select 0 = (Not QMB), 1 = QMB ("Quick Memory Bank")
|
||||||
|
//3 :
|
||||||
|
//4 : Home Select 0 = (Not HOME), 1 = HOME memory
|
||||||
|
//5 : Memory/MTUNE select 0 = Memory, 1 = MTUNE
|
||||||
|
//6 :
|
||||||
|
//7 : MEM/VFO Select 0 = Memory, 1 = VFO (A or B - see bit 0)
|
||||||
|
if (CAT_BUFF[2] & 0x01) //vfoB
|
||||||
|
{
|
||||||
|
//nowVFO Check
|
||||||
|
if (vfoActive != VFO_B)
|
||||||
|
{
|
||||||
|
CatVFOToggle(false, fromType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//vfoA
|
||||||
|
if (vfoActive != VFO_A)
|
||||||
|
{
|
||||||
|
CatVFOToggle(false, fromType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
case 0x57 : //
|
||||||
|
//0 : 1-0 AGC Mode 00 = Auto, 01 = Fast, 10 = Slow, 11 = Off
|
||||||
|
//2 DSP On/Off 0 = Off, 1 = On (Display format)
|
||||||
|
//4 PBT On/Off 0 = Off, 1 = On (Passband Tuning)
|
||||||
|
//5 NB On/Off 0 = Off, 1 = On (Noise Blanker)
|
||||||
|
//6 Lock On/Off 0 = Off, 1 = On (Dial Lock)
|
||||||
|
//7 FST (Fast Tuning) On/Off 0 = Off, 1 = On (Fast tuning)
|
||||||
|
|
||||||
|
CAT_BUFF[0] = 0xC0;
|
||||||
|
CAT_BUFF[1] = 0x40;
|
||||||
|
break;
|
||||||
|
case 0x59 : // band select VFO A Band Select 0000 = 160 M, 0001 = 75 M, 0010 = 40 M, 0011 = 30 M, 0100 = 20 M, 0101 = 17 M, 0110 = 15 M, 0111 = 12 M, 1000 = 10 M, 1001 = 6 M, 1010 = FM BCB, 1011 = Air, 1100 = 2 M, 1101 = UHF, 1110 = (Phantom)
|
||||||
|
//http://www.ka7oei.com/ft817_memmap.html
|
||||||
|
//CAT_BUFF[0] = 0xC2;
|
||||||
|
//CAT_BUFF[1] = 0x82;
|
||||||
|
break;
|
||||||
|
case 0x5C : //Beep Volume (0-100) (#13)
|
||||||
|
CAT_BUFF[0] = 0xB2;
|
||||||
|
CAT_BUFF[1] = 0x42;
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
case 0x5E :
|
||||||
|
//3-0 : CW Pitch (300-1000 Hz) (#20) From 0 to E (HEX) with 0 = 300 Hz and each step representing 50 Hz
|
||||||
|
//5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel
|
||||||
|
//7-6 : Op Filter (#38) 00 = Off, 01 = SSB, 10 = CW
|
||||||
|
sideTonePitch = (CAT_BUFF[2] & 0x0F);
|
||||||
|
|
||||||
|
if (sideTonePitch != 0 || sideToneSub != 0)
|
||||||
|
{
|
||||||
|
sideTone = (sideTonePitch * 50 + 300) + sideToneSub;
|
||||||
|
printLineF2(F("Sidetone set! CAT"));
|
||||||
|
EEPROM.put(CW_SIDETONE, sideTone);
|
||||||
|
delay(300); //If timeout errors occur in the calling software, remove them
|
||||||
|
clearLine2();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x61 : //Sidetone (Volume) (#44)
|
||||||
|
sideToneSub = (CAT_BUFF[2] & 0x7F);
|
||||||
|
if (sideTonePitch != 0 || sideToneSub != 0)
|
||||||
|
{
|
||||||
|
sideTone = (sideTonePitch * 50 + 300) + sideToneSub;
|
||||||
|
printLineF2(F("Sidetone set! CAT"));
|
||||||
|
EEPROM.put(CW_SIDETONE, sideTone);
|
||||||
|
delay(300); //If timeout errors occur in the calling software, remove them
|
||||||
|
clearLine2();
|
||||||
|
line2DisplayStatus = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
case 0x5F : //
|
||||||
|
//4-0 CW Weight (1.:2.5-1:4.5) (#22) From 0 to 14 (HEX) with 0 = 1:2.5, incrementing in 0.1 weight steps
|
||||||
|
//5 420 ARS (#2) 0 = Off, 1 = On
|
||||||
|
//6 144 ARS (#1) 0 = Off, 1 = On
|
||||||
|
//7 Sql/RF-G (#45) 0 = Off, 1 = On
|
||||||
|
CAT_BUFF[0] = 0x32;
|
||||||
|
CAT_BUFF[1] = 0x08;
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
case 0x60 : //CW Delay (10-2500 ms) (#17) From 1 to 250 (decimal) with each step representing 10 ms
|
||||||
|
//CAT_BUFF[0] = 0x19;
|
||||||
|
cwDelayTime = CAT_BUFF[2];
|
||||||
|
printLineF2(F("CW Speed set!"));
|
||||||
|
EEPROM.put(CW_DELAY, cwDelayTime);
|
||||||
|
delay(300);
|
||||||
|
clearLine2();
|
||||||
|
break;
|
||||||
|
case 0x62 : //
|
||||||
|
//5-0 CW Speed (4-60 WPM) (#21) From 0 to 38 (HEX) with 0 = 4 WPM and 38 = 60 WPM (1 WPM steps)
|
||||||
|
//7-6 Batt-Chg (6/8/10 Hours (#11) 00 = 6 Hours, 01 = 8 Hours, 10 = 10 Hours
|
||||||
|
cwSpeed = 1200 / ((CAT_BUFF[2] & 0x3F) + 4);
|
||||||
|
printLineF2(F("CW Speed set!"));
|
||||||
|
EEPROM.put(CW_SPEED, cwSpeed);
|
||||||
|
delay(300);
|
||||||
|
clearLine2();
|
||||||
|
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
case 0x63 : //
|
||||||
|
//6-0 VOX Gain (#51) Contains 1-100 (decimal) as displayed
|
||||||
|
//7 Disable AM/FM Dial (#4) 0 = Enable, 1 = Disable
|
||||||
|
CAT_BUFF[0] = 0xB2;
|
||||||
|
CAT_BUFF[1] = 0xA5;
|
||||||
|
break;
|
||||||
|
case 0x64 : //
|
||||||
|
//CAT_BUFF[0] = 0xA5;
|
||||||
|
//CAT_BUFF[1] = 0x00;
|
||||||
|
break;
|
||||||
|
case 0x67 : //6-0 SSB Mic (#46) Contains 0-100 (decimal) as displayed
|
||||||
|
CAT_BUFF[0] = 0xB2;
|
||||||
|
CAT_BUFF[1] = 0xB2;
|
||||||
|
//break; case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed
|
||||||
|
//CAT_BUFF[0] = 0x32;
|
||||||
|
//CAT_BUFF[1] = 0x32;
|
||||||
|
//break;
|
||||||
|
case 0x78 :
|
||||||
|
CAT_BUFF[0] = catGetMode();
|
||||||
|
// check, it must be a bit argument
|
||||||
|
if (CAT_BUFF[0] != 0) CAT_BUFF[0] = 1<<5;
|
||||||
|
break;
|
||||||
|
case 0x79 : //
|
||||||
|
//1-0 TX Power (All bands) 00 = High, 01 = L3, 10 = L2, 11 = L1
|
||||||
|
//3 PRI On/Off 0 = Off, 1 = On
|
||||||
|
//DW On/Off 0 = Off, 1 = On
|
||||||
|
//SCN (Scan) Mode 00 = No scan, 10 = Scan up, 11 = Scan down
|
||||||
|
//ART On/Off 0 = Off, 1 = On
|
||||||
|
CAT_BUFF[0] = 0x00;
|
||||||
|
CAT_BUFF[1] = 0x00;
|
||||||
|
break;
|
||||||
|
case 0x7A : //SPLIT
|
||||||
|
//7A 0 HF Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 1 6 M Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 2 FM BCB Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 3 Air Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 4 2 M Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 5 UHF Antenna Select 0 = Front, 1 = Rear
|
||||||
|
//7A 6 ? ?
|
||||||
|
//7A 7 SPL On/Off 0 = Off, 1 = On
|
||||||
|
|
||||||
|
CAT_BUFF[0] = (isSplitOn ? 0xFF : 0x7F);
|
||||||
|
break;
|
||||||
|
case 0xB3 : //
|
||||||
|
CAT_BUFF[0] = 0x00;
|
||||||
|
CAT_BUFF[1] = 0x4D;
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// sent the data
|
||||||
|
SendCatData(2);
|
||||||
|
Serial.write(ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CatRxStatus(byte fromType)
|
||||||
|
{
|
||||||
|
byte sMeterValue = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
http://www.ka7oei.com/ft817_meow.html
|
||||||
|
Command E7 - Read Receiver Status: This command returns one byte. Its contents are valid only when the '817 is in receive mode and it should be ignored when transmitting.
|
||||||
|
The lower 4 bits (0-3) of this byte indicate the current S-meter reading. 00 refers to an S-Zero reading, 04 = S4, 09 = S9, 0A = "10 over," 0B = "20 over" and so on up to 0F.
|
||||||
|
Bit 4 contains no useful information.
|
||||||
|
Bit 5 is 0 in non-FM modes, and it is 0 if the discriminator is centered (within 3.5 kHz for standard FM) when in the FM, FMN, or PKT modes, and 1 if the receiver is off-frequency.
|
||||||
|
Bit 6 is 0 if the CTCSS or DCS is turned off (or in a mode where it is not available.) It is also 0 if there is a signal being receive and the correct CTCSS tone or DCS code is being decoded.
|
||||||
|
It is 1 if there is a signal and the CTCSS/DCS decoding is enable, but the wrong CTCSS tone, DCS code, or no CTCSS/DCS is present.
|
||||||
|
Bit 7 is 0 if there is a signal present, or 1 if the receiver is squelched.
|
||||||
|
*/
|
||||||
|
// The lower 4 bits (0-3) of this byte indicate the current S-meter reading. 00 refers to an S-Zero reading, 04 = S4, 09 = S9, 0A = "10 over," 0B = "20 over" and so on up to 0F.
|
||||||
|
CAT_BUFF[0] = sMeterValue & 0b00001111;
|
||||||
|
SendCatData(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CatTxStatus(byte fromType)
|
||||||
|
{
|
||||||
|
boolean isHighSWR = false;
|
||||||
|
boolean isSplitOn = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Inverted -> *ptt = ((p->tx_status & 0x80) == 0); <-- souce code in ft817.c (hamlib)
|
||||||
|
*/
|
||||||
|
CAT_BUFF[0] = ((inTx ? 0 : 1) << 7) +
|
||||||
|
((isHighSWR ? 1 : 0) << 6) + //hi swr off / on
|
||||||
|
((isSplitOn ? 1 : 0) << 5) + //Split on / off
|
||||||
|
(0 << 4) + //dummy data
|
||||||
|
0x08; //P0 meter data
|
||||||
|
|
||||||
|
SendCatData(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long rxBufferArriveTime = 0;
|
||||||
|
byte rxBufferCheckCount = 0;
|
||||||
|
|
||||||
|
//Prevent Stack Overflow
|
||||||
|
byte isProcessCheck_Cat = 0;
|
||||||
|
|
||||||
|
//fromType normal : 0, TX : 1, CW_STRAIGHT : 2, CW_PADDLE : 3, CW_AUTOMODE : 4
|
||||||
|
//if cw mode, no delay
|
||||||
|
void Check_Cat(byte fromType)
|
||||||
|
{
|
||||||
|
byte i;
|
||||||
|
|
||||||
|
//Check Serial Port Buffer
|
||||||
|
if (Serial.available() == 0)
|
||||||
|
{
|
||||||
|
//Set Buffer Clear status
|
||||||
|
rxBufferCheckCount = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (Serial.available() < 5)
|
||||||
|
{
|
||||||
|
//First Arrived
|
||||||
|
if (rxBufferCheckCount == 0)
|
||||||
|
{
|
||||||
|
rxBufferCheckCount = Serial.available();
|
||||||
|
rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT; //Set time for timeout
|
||||||
|
}
|
||||||
|
else if (rxBufferArriveTime < millis()) //timeout
|
||||||
|
{
|
||||||
|
//Clear Buffer
|
||||||
|
for (i = 0; i < Serial.available(); i++)
|
||||||
|
rxBufferCheckCount = Serial.read();
|
||||||
|
|
||||||
|
rxBufferCheckCount = 0;
|
||||||
|
}
|
||||||
|
else if (rxBufferCheckCount < Serial.available()) //increase buffer count, slow arrived
|
||||||
|
{
|
||||||
|
rxBufferCheckCount = Serial.available();
|
||||||
|
rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT; //Set time for timeout
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Arived CAT DATA
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
CAT_BUFF[i] = Serial.read();
|
||||||
|
|
||||||
|
if (isProcessCheck_Cat == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
isProcessCheck_Cat = 1;
|
||||||
|
|
||||||
|
//reference : http://www.ka7oei.com/ft817_meow.html
|
||||||
|
switch(CAT_BUFF[4])
|
||||||
|
{
|
||||||
|
//The stability has not been verified and there seems to be no need. so i remarked codes,
|
||||||
|
//if you need, unmark lines
|
||||||
|
/*
|
||||||
|
case 0x00 : //Lock On
|
||||||
|
if (isDialLock == 1) //This command returns 00 if it was unlocked, and F0 if already locked.
|
||||||
|
CAT_BUFF[0] = 0xF0;
|
||||||
|
else {
|
||||||
|
CAT_BUFF[0] = 0x00;
|
||||||
|
setDialLock(1, fromType);
|
||||||
|
}
|
||||||
|
Serial.write(CAT_BUFF[0]); //Time
|
||||||
|
break;
|
||||||
|
case 0x80 : //Lock Off
|
||||||
|
if (isDialLock == 0) //This command returns 00 if the '817 was already locked, and F0 (HEX) if already unlocked.
|
||||||
|
CAT_BUFF[0] = 0xF0;
|
||||||
|
else {
|
||||||
|
CAT_BUFF[0] = 0x00;
|
||||||
|
setDialLock(0, fromType);
|
||||||
|
}
|
||||||
|
Serial.write(CAT_BUFF[0]); //Time
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
|
||||||
|
case 0x01 : //Set Frequency
|
||||||
|
CatSetFreq(fromType);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x02 : //Split On
|
||||||
|
case 0x82: //Split Off
|
||||||
|
CatSetSplit(CAT_BUFF[4] == 0x02, fromType);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x03 : //Read Frequency and mode
|
||||||
|
CatGetFreqMode(frequency, fromType);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x07 : //Set Operating Mode
|
||||||
|
CatSetMode(CAT_BUFF[0], fromType);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x08 : //Set PTT_ON
|
||||||
|
case 0x88: //Set PTT Off
|
||||||
|
CatSetPTT(CAT_BUFF[4] == 0x08, fromType);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x81: //Toggle VFO
|
||||||
|
CatVFOToggle(true, fromType);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xDB: //Read uBITX EEPROM Data
|
||||||
|
ReadEEPRom(fromType); //Call by uBITX Manager Program
|
||||||
|
break;
|
||||||
|
case 0xBB: //Read FT-817 EEPROM Data (for comfirtable)
|
||||||
|
ReadEEPRom_FT817(fromType);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xDC: //Write uBITX EEPROM Data
|
||||||
|
WriteEEPRom(fromType); //Call by uBITX Manager Program
|
||||||
|
break;
|
||||||
|
case 0xBC: //Write FT-817 EEPROM Data (for comfirtable)
|
||||||
|
WriteEEPRom_FT817(fromType);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xE7 : //Read RX Status
|
||||||
|
CatRxStatus(fromType);
|
||||||
|
break;
|
||||||
|
case 0xF7: //Read TX Status
|
||||||
|
CatTxStatus(fromType);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
char buff[16];
|
||||||
|
sprintf(buff, "DEFAULT : %x", CAT_BUFF[4]);
|
||||||
|
printLine2(buff);
|
||||||
|
*/
|
||||||
|
Serial.write(ACK);
|
||||||
|
break;
|
||||||
|
} //end of switch
|
||||||
|
|
||||||
|
isProcessCheck_Cat = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init_Cat(long baud, int portConfig)
|
||||||
|
{
|
||||||
|
Serial.begin(baud, portConfig);
|
||||||
|
Serial.flush();
|
||||||
|
}
|
||||||
|
|
417
ubitx_20/cw_autokey.ino
Normal file
417
ubitx_20/cw_autokey.ino
Normal file
@@ -0,0 +1,417 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
KD8CEC's Memory Keyer for HAM
|
||||||
|
|
||||||
|
This source code is written for All amateur radio operator,
|
||||||
|
I have not had amateur radio communication for a long time. CW has been
|
||||||
|
around for a long time, and I do not know what kind of keyer and keying
|
||||||
|
software is fashionable. So I implemented the functions I need mainly.
|
||||||
|
|
||||||
|
To minimize the use of memory space, we used bitwise operations.
|
||||||
|
For the alphabet, I put Morsecode in 1 byte. The front 4Bit is the length
|
||||||
|
and the 4Bit is the Morse code. Because the number is fixed in length,
|
||||||
|
there is no separate length information. The 5Bit on the right side is
|
||||||
|
the Morse code.
|
||||||
|
|
||||||
|
I wrote this code myself, so there is no license restriction.
|
||||||
|
So this code allows anyone to write with confidence.
|
||||||
|
But keep it as long as the original author of the code.
|
||||||
|
DE Ian KD8CEC
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
**************************************************************************/
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
//27 + 10 + 18 + 1(SPACE) = //56
|
||||||
|
const PROGMEM uint8_t cwAZTable[27] = {0b00100100 , 0b01001000 , 0b01001010 , 0b00111000 , 0b00010000, 0b01000010, 0b00111100, 0b01000000 , //A ~ H
|
||||||
|
0b00100000, 0b01000111 ,0b00111010, 0b01000100, 0b00101100, 0b00101000 , 0b00111110, 0b01000110, 0b01001101, 0b00110100, //I ~ R
|
||||||
|
0b00110000, 0b00011000, 0b00110010, 0b01000001, 0b00110110, 0b01001001, 0b01001011, 0b00111000}; //S ~ Z
|
||||||
|
PGM_P pCwAZTable = reinterpret_cast<PGM_P>(cwAZTable);
|
||||||
|
|
||||||
|
const PROGMEM uint8_t cw09Table[27] = {0b00011111, 0b00001111, 0b00000111, 0b00000011, 0b00000001, 0b00000000, 0b00010000, 0b00011000, 0b00011100, 0b00011110};
|
||||||
|
PGM_P pcw09Table = reinterpret_cast<PGM_P>(cw09Table);
|
||||||
|
|
||||||
|
//# : AR, ~:BT, [:AS, ]:SK, ^:KN
|
||||||
|
const PROGMEM uint8_t cwSymbolIndex[] = {'.', ',', '?', '"', '!', '/', '(', ')', '&', ':', ';', '=', '+', '-', '_', '\'', '@', '#', '~', '[', ']', '^' };
|
||||||
|
PGM_P pCwSymbolIndex = reinterpret_cast<PGM_P>(cwSymbolIndex);
|
||||||
|
|
||||||
|
const PROGMEM uint8_t cwSymbolTable[] = {0b11010101, 0b11110011, 0b11001100, 0b11011110, 0b11101011, 0b10100100, 0b10101100, 0b11101101, 0b10010000, 0b11111000, 0b11101010, 0b10100010, 0b10010100, 0b11100001, 0b11001101, 0b11010010, 0b11011010, 0b10010100, 0b10100010, 0b10010000, 0b11000101, 0b10101100};
|
||||||
|
PGM_P pCwSymbolTable = reinterpret_cast<PGM_P>(cwSymbolTable);
|
||||||
|
////const PROGMEM uint8_t cwSymbolLength[] = {6, 6, 6, 6, 6, 5, 5, 6, 5, 6, 6, 5, 5, 6, 6, 6, 6, 5, 5, 5, 6, 5};
|
||||||
|
|
||||||
|
// ":(Start"), ':(End "), >: My callsign, <:QSO Callsign (Second Callsign), #:AR, ~:BT, [:AS, ]:SK
|
||||||
|
|
||||||
|
byte knobPosition = 0;
|
||||||
|
//byte cwTextData[30]; //Maximum 30 Remarked by KD8CE -> Direct Read EEPROM
|
||||||
|
byte autoCWSendCharEndIndex = 0;
|
||||||
|
byte autoCWSendCharIndex = 0;
|
||||||
|
unsigned long autoCWbeforeTime = 0; //for interval time between chars
|
||||||
|
byte pttBeforeStatus = 1; //PTT : default high
|
||||||
|
byte isKeyStatusAfterCWStart = 0; //0 : Init, 1 : Keyup after auto CW Start, 2 : Keydown after
|
||||||
|
byte selectedCWTextIndex = 0;
|
||||||
|
unsigned long autoCWKeydownCheckTime = 0; //for interval time between chars
|
||||||
|
byte changeReserveStatus = 0;
|
||||||
|
byte isAutoCWHold = 0; //auto CW Pause => Manual Keying => auto
|
||||||
|
|
||||||
|
void autoSendPTTCheck()
|
||||||
|
{
|
||||||
|
if (isCWAutoMode == 2) { //Sending Mode
|
||||||
|
//check PTT Button
|
||||||
|
//short Press => reservation or cancel
|
||||||
|
//long Press => Hold
|
||||||
|
if (digitalRead(PTT) == LOW)
|
||||||
|
{
|
||||||
|
//if (isKeyStatusAfterCWStart == 0) //Yet Press PTT from start TX
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (isKeyStatusAfterCWStart == 1) //while auto cw send, ptt up and ptt down again
|
||||||
|
{
|
||||||
|
//Start Time
|
||||||
|
autoCWKeydownCheckTime = millis() + 200; //Long push time
|
||||||
|
isKeyStatusAfterCWStart = 2; //Change status => ptt down agian
|
||||||
|
}
|
||||||
|
else if (isKeyStatusAfterCWStart == 2 && autoCWKeydownCheckTime < millis())
|
||||||
|
{
|
||||||
|
//Hold Mode
|
||||||
|
isAutoCWHold = 1;
|
||||||
|
isKeyStatusAfterCWStart = 3;
|
||||||
|
}
|
||||||
|
else if (isKeyStatusAfterCWStart == 3)
|
||||||
|
{
|
||||||
|
autoCWKeydownCheckTime = millis() + 200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//PTT UP
|
||||||
|
if (isKeyStatusAfterCWStart == 2) //0 (down before cw start) -> 1 (up while cw sending) -> 2 (down while cw sending)
|
||||||
|
{
|
||||||
|
if (autoCWKeydownCheckTime > millis()) //Short : Reservation or cancel Next Text
|
||||||
|
{
|
||||||
|
if (autoCWSendReservCount == 0 ||
|
||||||
|
(autoCWSendReservCount < AUTO_CW_RESERVE_MAX &&
|
||||||
|
autoCWSendReserv[autoCWSendReservCount - 1] != selectedCWTextIndex))
|
||||||
|
{
|
||||||
|
//Reserve
|
||||||
|
autoCWSendReserv[autoCWSendReservCount++] = selectedCWTextIndex;
|
||||||
|
changeReserveStatus = 1;
|
||||||
|
}
|
||||||
|
else if (autoCWSendReservCount > 0 && autoCWSendReserv[autoCWSendReservCount - 1] == selectedCWTextIndex)
|
||||||
|
{
|
||||||
|
autoCWSendReservCount--;
|
||||||
|
changeReserveStatus = 1;
|
||||||
|
}
|
||||||
|
} // end of Short Key up
|
||||||
|
}
|
||||||
|
else if (isKeyStatusAfterCWStart == 3) //play from Hold (pause Auto CW Send)
|
||||||
|
{
|
||||||
|
isAutoCWHold = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
isKeyStatusAfterCWStart = 1; //Change status => ptt up (while cw send mode)
|
||||||
|
} //end of PTT UP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send 1 char
|
||||||
|
void sendCWChar(char cwKeyChar)
|
||||||
|
{
|
||||||
|
byte sendBuff[7];
|
||||||
|
byte i, j, charLength;
|
||||||
|
byte tmpChar;
|
||||||
|
|
||||||
|
//For Macrofunction
|
||||||
|
//replace > and < to My callsign, qso callsign, use recursive function call
|
||||||
|
if (cwKeyChar == '>' || cwKeyChar == '<')
|
||||||
|
{
|
||||||
|
uint16_t callsignStartIndex = 0;
|
||||||
|
uint16_t callsignEndIndex = 0;
|
||||||
|
|
||||||
|
if (cwKeyChar == '>') //replace my callsign
|
||||||
|
{
|
||||||
|
if (userCallsignLength > 0)
|
||||||
|
{
|
||||||
|
callsignStartIndex = 0;
|
||||||
|
callsignEndIndex = userCallsignLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cwKeyChar == '<') //replace qso callsign
|
||||||
|
{
|
||||||
|
//ReadLength
|
||||||
|
callsignEndIndex = EEPROM.read(CW_STATION_LEN);
|
||||||
|
if (callsignEndIndex > 0)
|
||||||
|
{
|
||||||
|
callsignStartIndex = CW_STATION_LEN - callsignEndIndex - USER_CALLSIGN_DAT;
|
||||||
|
callsignEndIndex = callsignStartIndex + callsignEndIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callsignStartIndex == 0 && callsignEndIndex == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (uint16_t i = callsignStartIndex; i <= callsignEndIndex; i++)
|
||||||
|
{
|
||||||
|
sendCWChar(EEPROM.read(USER_CALLSIGN_DAT + i));
|
||||||
|
autoSendPTTCheck(); //for reserve and cancel next CW Text
|
||||||
|
if (changeReserveStatus == 1)
|
||||||
|
{
|
||||||
|
changeReserveStatus = 0;
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < callsignEndIndex) delay_background(cwSpeed * 3, 4); //
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (cwKeyChar >= 'A' && cwKeyChar <= 'Z') //Encode Char by KD8CEC
|
||||||
|
{
|
||||||
|
tmpChar = pgm_read_byte(pCwAZTable + (cwKeyChar - 'A'));
|
||||||
|
charLength = (tmpChar >> 4) & 0x0F;
|
||||||
|
for (i = 0; i < charLength; i++)
|
||||||
|
sendBuff[i] = (tmpChar << i) & 0x08;
|
||||||
|
}
|
||||||
|
else if (cwKeyChar >= '0' && cwKeyChar <= '9')
|
||||||
|
{
|
||||||
|
charLength = 5;
|
||||||
|
for (i = 0; i < charLength; i++)
|
||||||
|
sendBuff[i] = (pgm_read_byte(pcw09Table + (cwKeyChar - '0')) << i) & 0x10;
|
||||||
|
}
|
||||||
|
else if (cwKeyChar == ' ')
|
||||||
|
{
|
||||||
|
charLength = 0;
|
||||||
|
delay_background(cwSpeed * 4, 4); //7 -> basic interval is 3
|
||||||
|
}
|
||||||
|
else if (cwKeyChar == '$') //7 digit
|
||||||
|
{
|
||||||
|
charLength = 7;
|
||||||
|
for (i = 0; i < 7; i++)
|
||||||
|
sendBuff[i] = (0b00010010 << i) & 0x80; //...1..1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//symbol
|
||||||
|
for (i = 0; i < 22; i++)
|
||||||
|
{
|
||||||
|
if (pgm_read_byte(pCwSymbolIndex + i) == cwKeyChar)
|
||||||
|
{
|
||||||
|
tmpChar = pgm_read_byte(pCwSymbolTable + i);
|
||||||
|
charLength = ((tmpChar >> 6) & 0x03) + 3;
|
||||||
|
|
||||||
|
for (j = 0; j < charLength; j++)
|
||||||
|
sendBuff[j] = (tmpChar << (j + 2)) & 0x80;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
charLength = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < charLength; i++)
|
||||||
|
{
|
||||||
|
cwKeydown();
|
||||||
|
if (sendBuff[i] == 0)
|
||||||
|
delay_background(cwSpeed, 4);
|
||||||
|
else
|
||||||
|
delay_background(cwSpeed * 3, 4);
|
||||||
|
cwKeyUp();
|
||||||
|
if (i != charLength -1)
|
||||||
|
delay_background(cwSpeed, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void sendAutoCW(int cwSendLength, char *sendString)
|
||||||
|
{
|
||||||
|
byte i;
|
||||||
|
|
||||||
|
if (!inTx){
|
||||||
|
keyDown = 0;
|
||||||
|
cwTimeout = millis() + cwDelayTime * 10;
|
||||||
|
startTx(TX_CW, 0); //disable updateDisplay Command for reduce latency time
|
||||||
|
updateDisplay();
|
||||||
|
|
||||||
|
delay_background(delayBeforeCWStartTime * 2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < cwSendLength; i++)
|
||||||
|
{
|
||||||
|
sendCWChar(sendString[i]);
|
||||||
|
if (i != cwSendLength -1) delay_background(cwSpeed * 3, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
delay_background(cwDelayTime * 10, 2);
|
||||||
|
stopTx();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
byte isNeedScroll = 0;
|
||||||
|
unsigned long scrollDispayTime = 0;
|
||||||
|
#define scrollSpeed 500
|
||||||
|
byte displayScrolStep = 0;
|
||||||
|
|
||||||
|
void controlAutoCW(){
|
||||||
|
int knob = 0;
|
||||||
|
byte i;
|
||||||
|
|
||||||
|
byte cwStartIndex, cwEndIndex;
|
||||||
|
|
||||||
|
if (cwAutoDialType == 0)
|
||||||
|
knob = enc_read();
|
||||||
|
|
||||||
|
if (knob != 0 || beforeCWTextIndex == 255 || isNeedScroll == 1){ //start display
|
||||||
|
if (knobPosition > 0 && knob < 0)
|
||||||
|
knobPosition--;
|
||||||
|
if (knobPosition < cwAutoTextCount * 10 -1 && knob > 0)
|
||||||
|
knobPosition++;
|
||||||
|
|
||||||
|
selectedCWTextIndex = knobPosition / 10;
|
||||||
|
|
||||||
|
if ((beforeCWTextIndex != selectedCWTextIndex) ||
|
||||||
|
(isNeedScroll == 1 && beforeCWTextIndex == selectedCWTextIndex && scrollDispayTime < millis())) {
|
||||||
|
//Read CW Text Data Position From EEProm
|
||||||
|
EEPROM.get(CW_AUTO_DATA + (selectedCWTextIndex * 2), cwStartIndex);
|
||||||
|
EEPROM.get(CW_AUTO_DATA + (selectedCWTextIndex * 2 + 1), cwEndIndex);
|
||||||
|
|
||||||
|
if (beforeCWTextIndex == selectedCWTextIndex)
|
||||||
|
{
|
||||||
|
if (++displayScrolStep > cwEndIndex - cwStartIndex)
|
||||||
|
displayScrolStep = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
displayScrolStep = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printLineFromEEPRom(0, 2, cwStartIndex + displayScrolStep + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ);
|
||||||
|
|
||||||
|
byte diplayAutoCWLine = 0;
|
||||||
|
if ((displayOption1 & 0x01) == 0x01)
|
||||||
|
diplayAutoCWLine = 1;
|
||||||
|
|
||||||
|
lcd.setCursor(0, diplayAutoCWLine);
|
||||||
|
lcd.write(byteToChar(selectedCWTextIndex));
|
||||||
|
lcd.write(':');
|
||||||
|
isNeedScroll = (cwEndIndex - cwStartIndex) > 14 ? 1 : 0;
|
||||||
|
scrollDispayTime = millis() + scrollSpeed;
|
||||||
|
beforeCWTextIndex = selectedCWTextIndex;
|
||||||
|
}
|
||||||
|
} //end of check knob
|
||||||
|
|
||||||
|
if (isCWAutoMode == 1) { //ready status
|
||||||
|
if (digitalRead(PTT) == LOW) //PTT Down : Start Auto CW or DialMode Change
|
||||||
|
{
|
||||||
|
if (pttBeforeStatus == 1) //High to Low Change
|
||||||
|
{
|
||||||
|
autoCWbeforeTime = millis() + 500; //Long push time
|
||||||
|
pttBeforeStatus = 0;
|
||||||
|
}
|
||||||
|
else if (autoCWbeforeTime < millis()) //while press PTT, OK Long push then Send Auto CW Text
|
||||||
|
{
|
||||||
|
sendingCWTextIndex = selectedCWTextIndex;
|
||||||
|
|
||||||
|
//Information about Auto Send CW Text
|
||||||
|
autoCWSendCharEndIndex = cwEndIndex; //length of CW Text //ianlee
|
||||||
|
autoCWSendCharIndex = cwStartIndex; //position of Sending Char //ianlee
|
||||||
|
|
||||||
|
isCWAutoMode = 2; //auto sending start
|
||||||
|
autoCWbeforeTime = 0; //interval between chars, 0 = always send
|
||||||
|
isKeyStatusAfterCWStart = 0; //Init PTT Key status
|
||||||
|
autoCWSendReservCount = 0; //Init Reserve Count
|
||||||
|
isAutoCWHold = 0;
|
||||||
|
if (!inTx){ //if not TX Status, change RX -> TX
|
||||||
|
keyDown = 0;
|
||||||
|
startTx(TX_CW, 0); //disable updateDisplay Command for reduce latency time
|
||||||
|
updateDisplay();
|
||||||
|
|
||||||
|
delay_background(delayBeforeCWStartTime * 2, 2); //for External AMP or personal situation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pttBeforeStatus == 0 && autoCWbeforeTime > 0) //while reade status LOW -> HIGH (before Auto send Before)
|
||||||
|
{
|
||||||
|
pttBeforeStatus = 1; //HIGH
|
||||||
|
if (autoCWbeforeTime > millis()) //short Press -> ? DialModeChange
|
||||||
|
{
|
||||||
|
cwAutoDialType = (cwAutoDialType == 1 ? 0 : 1); //Invert DialMode between select CW Text and Frequency Tune
|
||||||
|
if (cwAutoDialType == 0)
|
||||||
|
printLineF1(F("Dial:Select Text"));
|
||||||
|
else
|
||||||
|
printLineF1(F("Dial:Freq Tune"));
|
||||||
|
|
||||||
|
delay_background(1000, 0);
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} //end of isCWAutoMode == 1 condition
|
||||||
|
|
||||||
|
if (isCWAutoMode == 2) { //Sending Mode
|
||||||
|
autoSendPTTCheck();
|
||||||
|
|
||||||
|
//check interval time, if you want adjust interval between chars, modify below
|
||||||
|
if (isAutoCWHold == 0 && (millis() - autoCWbeforeTime > cwSpeed * 3))
|
||||||
|
{
|
||||||
|
sendCWChar(EEPROM.read(CW_AUTO_DATA + autoCWSendCharIndex++));
|
||||||
|
|
||||||
|
if (autoCWSendCharIndex > autoCWSendCharEndIndex) { //finish auto cw send
|
||||||
|
//check reserve status
|
||||||
|
if (autoCWSendReservCount > 0)
|
||||||
|
{
|
||||||
|
//prepare
|
||||||
|
sendingCWTextIndex = autoCWSendReserv[0];
|
||||||
|
|
||||||
|
for (i = 0; i < AUTO_CW_RESERVE_MAX -1; i++)
|
||||||
|
autoCWSendReserv[i] = autoCWSendReserv[i + 1];
|
||||||
|
|
||||||
|
EEPROM.get(CW_AUTO_DATA + (sendingCWTextIndex * 2), cwStartIndex);
|
||||||
|
EEPROM.get(CW_AUTO_DATA + (sendingCWTextIndex * 2 + 1), cwEndIndex);
|
||||||
|
|
||||||
|
//Information about Auto Send CW Text
|
||||||
|
autoCWSendCharEndIndex = cwEndIndex; //length of CW Text //ianlee
|
||||||
|
autoCWSendCharIndex = cwStartIndex; //position of Sending Char //ianlee
|
||||||
|
autoCWSendReservCount--; //Decrease
|
||||||
|
|
||||||
|
sendCWChar(' '); //APPLY SPACE between CW Texts
|
||||||
|
changeReserveStatus = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isCWAutoMode = 1; //ready status
|
||||||
|
delay_background(cwDelayTime * 10, 2);
|
||||||
|
stopTx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
autoCWbeforeTime = millis();
|
||||||
|
|
||||||
|
if (changeReserveStatus == 1)
|
||||||
|
{
|
||||||
|
changeReserveStatus = 0;
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//abort if this button is down
|
||||||
|
if (btnDown())
|
||||||
|
{
|
||||||
|
isCWAutoMode = 0; //dsiable Auto CW Mode
|
||||||
|
printLine2ClearAndUpdate();
|
||||||
|
delay_background(1000, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -1,4 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
|
Since KD8CEC Version 0.29, most of the original code is no longer available.
|
||||||
|
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
|
||||||
|
|
||||||
|
Original source comment -------------------------------------------------------------
|
||||||
* This source file is under General Public License version 3.
|
* This source file is under General Public License version 3.
|
||||||
*
|
*
|
||||||
* This verision uses a built-in Si5351 library
|
* This verision uses a built-in Si5351 library
|
||||||
@@ -78,6 +84,7 @@
|
|||||||
#define PTT (A3)
|
#define PTT (A3)
|
||||||
#define ANALOG_KEYER (A6)
|
#define ANALOG_KEYER (A6)
|
||||||
#define ANALOG_SPARE (A7)
|
#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:
|
* The Raduino board is the size of a standard 16x2 LCD panel. It has three connectors:
|
||||||
@@ -96,6 +103,8 @@
|
|||||||
#include <LiquidCrystal.h>
|
#include <LiquidCrystal.h>
|
||||||
LiquidCrystal lcd(8,9,10,11,12,13);
|
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.
|
* 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
|
* We have to be very careful with variables that are declared inside the functions as they are
|
||||||
@@ -141,6 +150,50 @@ int count = 0; //to generally count ticks, loops, etc
|
|||||||
#define CW_SIDETONE 24
|
#define CW_SIDETONE 24
|
||||||
#define CW_SPEED 28
|
#define CW_SPEED 28
|
||||||
|
|
||||||
|
//AT328 has 1KBytes EEPROM
|
||||||
|
#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)
|
||||||
|
|
||||||
|
//for reduce cw key error, eeprom address
|
||||||
|
#define CW_ADC_MOST_BIT1 348 //most 2bits of DOT_TO , DOT_FROM, ST_TO, ST_FROM
|
||||||
|
#define CW_ADC_ST_FROM 349 //CW ADC Range STRAIGHT KEY from (Lower 8 bit)
|
||||||
|
#define CW_ADC_ST_TO 350 //CW ADC Range STRAIGHT KEY to (Lower 8 bit)
|
||||||
|
#define CW_ADC_DOT_FROM 351 //CW ADC Range DOT from (Lower 8 bit)
|
||||||
|
#define CW_ADC_DOT_TO 352 //CW ADC Range DOT to (Lower 8 bit)
|
||||||
|
|
||||||
|
#define CW_ADC_MOST_BIT2 353 //most 2bits of BOTH_TO, BOTH_FROM, DASH_TO, DASH_FROM
|
||||||
|
#define CW_ADC_DASH_FROM 354 //CW ADC Range DASH from (Lower 8 bit)
|
||||||
|
#define CW_ADC_DASH_TO 355 //CW ADC Range DASH to (Lower 8 bit)
|
||||||
|
#define CW_ADC_BOTH_FROM 356 //CW ADC Range BOTH from (Lower 8 bit)
|
||||||
|
#define CW_ADC_BOTH_TO 357 //CW ADC Range BOTH to (Lower 8 bit)
|
||||||
|
#define CW_KEY_TYPE 358
|
||||||
|
|
||||||
|
#define DISPLAY_OPTION1 361 //Display Option1
|
||||||
|
#define DISPLAY_OPTION2 362 //Display Option2
|
||||||
|
|
||||||
|
//Check Firmware type and version
|
||||||
|
#define FIRMWAR_ID_ADDR 776 //776 : 0x59, 777 :0x58, 778 : 0x68 : Id Number, if not found id, erase eeprom(32~1023) for prevent system error.
|
||||||
|
#define VERSION_ADDRESS 779 //check Firmware version
|
||||||
|
//USER INFORMATION
|
||||||
|
#define USER_CALLSIGN_KEY 780 //0x59
|
||||||
|
#define USER_CALLSIGN_LEN 781 //1BYTE (OPTION + LENGTH) + CALLSIGN (MAXIMUM 18)
|
||||||
|
#define USER_CALLSIGN_DAT 782 //CALL SIGN DATA //direct EEPROM to LCD basic offset
|
||||||
|
|
||||||
|
//AUTO KEY STRUCTURE
|
||||||
|
//AUTO KEY USE 800 ~ 1023
|
||||||
|
#define CW_AUTO_MAGIC_KEY 800 //0x73
|
||||||
|
#define CW_AUTO_COUNT 801 //0 ~ 255
|
||||||
|
#define CW_AUTO_DATA 803 //[INDEX, INDEX, INDEX,DATA,DATA, DATA (Positon offset is CW_AUTO_DATA
|
||||||
|
#define CW_DATA_OFSTADJ CW_AUTO_DATA - USER_CALLSIGN_DAT //offset adjust for ditect eeprom to lcd (basic offset is USER_CALLSIGN_DAT
|
||||||
|
#define CW_STATION_LEN 1023 //value range : 4 ~ 30
|
||||||
/**
|
/**
|
||||||
* The uBITX is an upconnversion transceiver. The first IF is at 45 MHz.
|
* The uBITX is an upconnversion transceiver. The first IF is at 45 MHz.
|
||||||
* The first IF frequency is not exactly at 45 Mhz but about 5 khz lower,
|
* The first IF frequency is not exactly at 45 Mhz but about 5 khz lower,
|
||||||
@@ -168,6 +221,10 @@ int count = 0; //to generally count ticks, loops, etc
|
|||||||
#define LOWEST_FREQ (3000000l)
|
#define LOWEST_FREQ (3000000l)
|
||||||
#define HIGHEST_FREQ (30000000l)
|
#define HIGHEST_FREQ (30000000l)
|
||||||
|
|
||||||
|
//When the frequency is moved by the dial, the maximum value by KD8CEC
|
||||||
|
#define LOWEST_FREQ_DIAL (3000l)
|
||||||
|
#define HIGHEST_FREQ_DIAL (60000000l)
|
||||||
|
|
||||||
//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes
|
//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
|
//these are the parameter passed to startTx
|
||||||
#define TX_SSB 0
|
#define TX_SSB 0
|
||||||
@@ -176,20 +233,78 @@ int count = 0; //to generally count ticks, loops, etc
|
|||||||
char ritOn = 0;
|
char ritOn = 0;
|
||||||
char vfoActive = VFO_A;
|
char vfoActive = VFO_A;
|
||||||
int8_t meter_reading = 0; // a -1 on meter makes it invisible
|
int8_t meter_reading = 0; // a -1 on meter makes it invisible
|
||||||
unsigned long vfoA=7150000L, vfoB=14200000L, sideTone=800, usbCarrier;
|
unsigned long vfoA=7150000L, vfoB=14200000L, sideTone=800, usbCarrier, cwmCarrier;
|
||||||
|
unsigned long vfoA_eeprom, vfoB_eeprom; //for protect eeprom life
|
||||||
unsigned long frequency, ritRxFrequency, ritTxFrequency; //frequency is the current frequency on the dial
|
unsigned long frequency, ritRxFrequency, ritTxFrequency; //frequency is the current frequency on the dial
|
||||||
|
|
||||||
int cwSpeed = 100; //this is actuall the dot period in milliseconds
|
unsigned int cwSpeed = 100; //this is actuall the dot period in milliseconds
|
||||||
extern int32_t calibration;
|
extern int32_t calibration;
|
||||||
|
|
||||||
|
//for store the mode in eeprom
|
||||||
|
byte vfoA_mode=0, vfoB_mode = 0; //0: default, 1:not use, 2:LSB, 3:USB, 4:CW, 5:AM, 6:FM
|
||||||
|
byte vfoA_mode_eeprom, vfoB_mode_eeprom; //for protect eeprom life
|
||||||
|
|
||||||
|
//KD8CEC
|
||||||
|
//for AutoSave and protect eeprom life
|
||||||
|
byte saveIntervalSec = 10; //second
|
||||||
|
unsigned long saveCheckTime = 0;
|
||||||
|
unsigned long saveCheckFreq = 0;
|
||||||
|
|
||||||
|
byte cwDelayTime = 60;
|
||||||
|
byte delayBeforeCWStartTime = 50;
|
||||||
|
|
||||||
|
//sideTonePitch + sideToneSub = sideTone
|
||||||
|
byte sideTonePitch=0;
|
||||||
|
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];
|
||||||
|
byte tuneStepIndex; //default Value 0, start Offset is 0 because of check new user
|
||||||
|
|
||||||
|
byte displayOption1 = 0;
|
||||||
|
byte displayOption2 = 0;
|
||||||
|
|
||||||
|
//CW ADC Range
|
||||||
|
int cwAdcSTFrom = 0;
|
||||||
|
int cwAdcSTTo = 0;
|
||||||
|
int cwAdcDotFrom = 0;
|
||||||
|
int cwAdcDotTo = 0;
|
||||||
|
int cwAdcDashFrom = 0;
|
||||||
|
int cwAdcDashTo = 0;
|
||||||
|
int cwAdcBothFrom = 0;
|
||||||
|
int cwAdcBothTo = 0;
|
||||||
|
byte cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
||||||
|
bool Iambic_Key = true;
|
||||||
|
#define IAMBICB 0x10 // 0 for Iambic A, 1 for Iambic B
|
||||||
|
unsigned char keyerControl = IAMBICB;
|
||||||
|
|
||||||
|
//Variables for auto cw mode
|
||||||
|
byte isCWAutoMode = 0; //0 : none, 1 : CW_AutoMode_Menu_Selection, 2 : CW_AutoMode Sending
|
||||||
|
byte cwAutoTextCount = 0; //cwAutoText Count
|
||||||
|
byte beforeCWTextIndex = 255; //when auto cw start, always beforeCWTextIndex = 255, (for first time check)
|
||||||
|
byte cwAutoDialType = 0; //0 : CW Text Change, 1 : Frequency Tune
|
||||||
|
|
||||||
|
#define AUTO_CW_RESERVE_MAX 3
|
||||||
|
byte autoCWSendReserv[AUTO_CW_RESERVE_MAX]; //Reserve CW Auto Send
|
||||||
|
byte autoCWSendReservCount = 0; //Reserve CW Text Cound
|
||||||
|
byte sendingCWTextIndex = 0; //cw auto seding Text Index
|
||||||
|
|
||||||
|
byte userCallsignLength = 0; //7 : display callsign at system startup, 6~0 : callsign length (range : 1~18)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raduino needs to keep track of current state of the transceiver. These are a few variables that do it
|
* Raduino needs to keep track of current state of the transceiver. These are a few variables that do it
|
||||||
*/
|
*/
|
||||||
boolean txCAT = false; //turned on if the transmitting due to a CAT command
|
boolean txCAT = false; //turned on if the transmitting due to a CAT command
|
||||||
char inTx = 0; //it is set to 1 if in transmit mode (whatever the reason : cw, ptt or cat)
|
char inTx = 0; //it is set to 1 if in transmit mode (whatever the reason : cw, ptt or cat)
|
||||||
char splitOn = 0; //working split, uses VFO B as the transmit frequency, (NOT IMPLEMENTED YET)
|
char splitOn = 0; //working split, uses VFO B as the transmit frequency
|
||||||
char keyDown = 0; //in cw mode, denotes the carrier is being transmitted
|
char keyDown = 0; //in cw mode, denotes the carrier is being transmitted
|
||||||
char isUSB = 0; //upper sideband was selected, this is reset to the default for the
|
char isUSB = 0; //upper sideband was selected, this is reset to the default for the
|
||||||
|
|
||||||
|
char cwMode = 0; //compatible original source, and extend mode //if cwMode == 0, mode check : isUSB, cwMode > 0, mode Check : cwMode
|
||||||
|
//iscwMode = 0 : ssbmode, 1 :cwl, 2 : cwu, 3 : cwn (none tx)
|
||||||
|
|
||||||
//frequency when it crosses the frequency border of 10 MHz
|
//frequency when it crosses the frequency border of 10 MHz
|
||||||
byte menuOn = 0; //set to 1 when the menu is being displayed, if a menu item sets it to zero, the menu is exited
|
byte menuOn = 0; //set to 1 when the menu is being displayed, if a menu item sets it to zero, the menu is exited
|
||||||
unsigned long cwTimeout = 0; //milliseconds to go before the cw transmit line is released and the radio goes back to rx mode
|
unsigned long cwTimeout = 0; //milliseconds to go before the cw transmit line is released and the radio goes back to rx mode
|
||||||
@@ -197,11 +312,119 @@ unsigned long dbgCount = 0; //not used now
|
|||||||
unsigned char txFilter = 0; //which of the four transmit filters are in use
|
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
|
boolean modeCalibrate = false;//this mode of menus shows extended menus to calibrate the oscillators and choose the proper
|
||||||
//beat frequency
|
//beat frequency
|
||||||
|
|
||||||
|
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
|
||||||
|
long ifShiftValue = 0; //
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Below are the basic functions that control the uBitx. Understanding the functions before
|
* Below are the basic functions that control the uBitx. Understanding the functions before
|
||||||
* you start hacking around
|
* you start hacking around
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//Ham Band
|
||||||
|
#define MAX_LIMIT_RANGE 10 //because limited eeprom size
|
||||||
|
byte useHamBandCount = 0; //0 use full range frequency
|
||||||
|
byte tuneTXType = 0; //0 : use full range, 1 : just Change Dial speed, 2 : just ham band change, but can general band by tune, 3 : only ham band (just support 0, 2 (0.26 version))
|
||||||
|
//100 : use full range but not TX on general band, 101 : just change dial speed but.. 2 : jut... but.. 3 : only ham band (just support 100, 102 (0.26 version))
|
||||||
|
unsigned int hamBandRange[MAX_LIMIT_RANGE][2]; // = //Khz because reduce use memory
|
||||||
|
|
||||||
|
//-1 : not found, 0 ~ 9 : Hamband index
|
||||||
|
char getIndexHambanBbyFreq(unsigned long f)
|
||||||
|
{
|
||||||
|
f = f / 1000;
|
||||||
|
for (byte i = 0; i < useHamBandCount; i++)
|
||||||
|
if (hamBandRange[i][0] <= f && f < hamBandRange[i][1])
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//when Band change step = just hamband
|
||||||
|
//moveDirection : 1 = next, -1 : prior
|
||||||
|
void setNextHamBandFreq(unsigned long f, char moveDirection)
|
||||||
|
{
|
||||||
|
unsigned long resultFreq = 0;
|
||||||
|
byte loadMode = 0;
|
||||||
|
char findedIndex = getIndexHambanBbyFreq(f);
|
||||||
|
|
||||||
|
if (findedIndex == -1) { //out of hamband
|
||||||
|
f = f / 1000;
|
||||||
|
for (byte i = 0; i < useHamBandCount -1; i++) {
|
||||||
|
if (hamBandRange[i][1] <= f && f < hamBandRange[i + 1][0]) {
|
||||||
|
findedIndex = i + moveDirection;
|
||||||
|
//return (unsigned long)(hamBandRange[i + 1][0]) * 1000;
|
||||||
|
}
|
||||||
|
} //end of for
|
||||||
|
}
|
||||||
|
else if (((moveDirection == 1) && (findedIndex < useHamBandCount -1)) || //Next
|
||||||
|
((moveDirection == -1) && (findedIndex > 0)) ) { //Prior
|
||||||
|
findedIndex += moveDirection;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
findedIndex = -1;
|
||||||
|
|
||||||
|
if (findedIndex == -1)
|
||||||
|
findedIndex = (moveDirection == 1 ? 0 : useHamBandCount -1);
|
||||||
|
|
||||||
|
EEPROM.get(HAM_BAND_FREQS + 4 * findedIndex, resultFreq);
|
||||||
|
|
||||||
|
//loadMode = (byte)(resultFreq >> 30);
|
||||||
|
//resultFreq = resultFreq & 0x3FFFFFFF;
|
||||||
|
loadMode = (byte)(resultFreq >> 29);
|
||||||
|
resultFreq = resultFreq & 0x1FFFFFFF;
|
||||||
|
|
||||||
|
if ((resultFreq / 1000) < hamBandRange[(unsigned char)findedIndex][0] || (resultFreq / 1000) > hamBandRange[(unsigned char)findedIndex][1])
|
||||||
|
resultFreq = (unsigned long)(hamBandRange[(unsigned char)findedIndex][0]) * 1000;
|
||||||
|
|
||||||
|
setFrequency(resultFreq);
|
||||||
|
byteWithFreqToMode(loadMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveBandFreqByIndex(unsigned long f, unsigned long mode, char bandIndex) {
|
||||||
|
if (bandIndex >= 0)
|
||||||
|
//EEPROM.put(HAM_BAND_FREQS + 4 * bandIndex, (f & 0x3FFFFFFF) | (mode << 30) );
|
||||||
|
EEPROM.put(HAM_BAND_FREQS + 4 * bandIndex, (f & 0x1FFFFFFF) | (mode << 29) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
KD8CEC
|
||||||
|
When using the basic delay of the Arduino, the program freezes.
|
||||||
|
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();
|
||||||
|
|
||||||
|
while (millis() - delayBeforeTime <= delayTime) {
|
||||||
|
|
||||||
|
if (fromType == 4)
|
||||||
|
{
|
||||||
|
//CHECK PADDLE
|
||||||
|
if (getPaddle() != 0) //Interrupt : Stop cw Auto mode by Paddle -> Change Auto to Manual
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
//Check PTT while auto Sending
|
||||||
|
autoSendPTTCheck();
|
||||||
|
|
||||||
|
Check_Cat(3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Background Work
|
||||||
|
Check_Cat(fromType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select the properly tx harmonic filters
|
* Select the properly tx harmonic filters
|
||||||
* The four harmonic filters use only three relays
|
* The four harmonic filters use only three relays
|
||||||
@@ -256,17 +479,31 @@ void setTXFilters(unsigned long freq){
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void setFrequency(unsigned long f){
|
void setFrequency(unsigned long f){
|
||||||
uint64_t osc_f;
|
f = (f / arTuneStep[tuneStepIndex -1]) * arTuneStep[tuneStepIndex -1];
|
||||||
|
|
||||||
setTXFilters(f);
|
setTXFilters(f);
|
||||||
|
|
||||||
if (isUSB){
|
if (cwMode == 0)
|
||||||
si5351bx_setfreq(2, SECOND_OSC_USB - usbCarrier + f);
|
{
|
||||||
si5351bx_setfreq(1, SECOND_OSC_USB);
|
if (isUSB){
|
||||||
|
si5351bx_setfreq(2, SECOND_OSC_USB - usbCarrier + f + (isIFShift ? ifShiftValue : 0));
|
||||||
|
si5351bx_setfreq(1, SECOND_OSC_USB);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
si5351bx_setfreq(2, SECOND_OSC_LSB + usbCarrier + f + (isIFShift ? ifShiftValue : 0));
|
||||||
|
si5351bx_setfreq(1, SECOND_OSC_LSB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
si5351bx_setfreq(2, SECOND_OSC_LSB + usbCarrier + f);
|
{
|
||||||
si5351bx_setfreq(1, SECOND_OSC_LSB);
|
if (cwMode == 1){ //CWL
|
||||||
|
si5351bx_setfreq(2, SECOND_OSC_LSB + cwmCarrier + f + (isIFShift ? ifShiftValue : 0));
|
||||||
|
si5351bx_setfreq(1, SECOND_OSC_LSB);
|
||||||
|
}
|
||||||
|
else{ //CWU
|
||||||
|
si5351bx_setfreq(2, SECOND_OSC_USB - cwmCarrier + f + (isIFShift ? ifShiftValue : 0));
|
||||||
|
si5351bx_setfreq(1, SECOND_OSC_USB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frequency = f;
|
frequency = f;
|
||||||
@@ -278,9 +515,16 @@ void setFrequency(unsigned long f){
|
|||||||
* Note: In cw mode, doesnt key the radio, only puts it in tx mode
|
* Note: In cw mode, doesnt key the radio, only puts it in tx mode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void startTx(byte txMode){
|
void startTx(byte txMode, byte isDisplayUpdate){
|
||||||
unsigned long tx_freq = 0;
|
//Check Hamband only TX //Not found Hamband index by now frequency
|
||||||
digitalWrite(TX_RX, 1);
|
if (tuneTXType >= 100 && getIndexHambanBbyFreq(ritOn ? ritTxFrequency : frequency) == -1) {
|
||||||
|
//no message
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((isTxType & 0x01) != 0x01)
|
||||||
|
digitalWrite(TX_RX, 1);
|
||||||
|
|
||||||
inTx = 1;
|
inTx = 1;
|
||||||
|
|
||||||
if (ritOn){
|
if (ritOn){
|
||||||
@@ -288,6 +532,21 @@ void startTx(byte txMode){
|
|||||||
ritRxFrequency = frequency;
|
ritRxFrequency = frequency;
|
||||||
setFrequency(ritTxFrequency);
|
setFrequency(ritTxFrequency);
|
||||||
}
|
}
|
||||||
|
else if (splitOn == 1) {
|
||||||
|
if (vfoActive == VFO_B) {
|
||||||
|
vfoActive = VFO_A;
|
||||||
|
frequency = vfoA;
|
||||||
|
byteToMode(vfoA_mode);
|
||||||
|
}
|
||||||
|
else if (vfoActive == VFO_A){
|
||||||
|
vfoActive = VFO_B;
|
||||||
|
frequency = vfoB;
|
||||||
|
byteToMode(vfoB_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
setFrequency(frequency);
|
||||||
|
} //end of else
|
||||||
|
|
||||||
|
|
||||||
if (txMode == TX_CW){
|
if (txMode == TX_CW){
|
||||||
//turn off the second local oscillator and the bfo
|
//turn off the second local oscillator and the bfo
|
||||||
@@ -297,22 +556,55 @@ void startTx(byte txMode){
|
|||||||
//shif the first oscillator to the tx frequency directly
|
//shif the first oscillator to the tx frequency directly
|
||||||
//the key up and key down will toggle the carrier unbalancing
|
//the key up and key down will toggle the carrier unbalancing
|
||||||
//the exact cw frequency is the tuned frequency + sidetone
|
//the exact cw frequency is the tuned frequency + sidetone
|
||||||
if (isUSB)
|
|
||||||
si5351bx_setfreq(2, frequency + sideTone);
|
if (cwMode == 0)
|
||||||
else
|
{
|
||||||
si5351bx_setfreq(2, frequency - sideTone);
|
if (isUSB)
|
||||||
|
si5351bx_setfreq(2, frequency + sideTone);
|
||||||
|
else
|
||||||
|
si5351bx_setfreq(2, frequency - sideTone);
|
||||||
|
}
|
||||||
|
else if (cwMode == 1) //CWL
|
||||||
|
{
|
||||||
|
si5351bx_setfreq(2, frequency - sideTone);
|
||||||
|
}
|
||||||
|
else //CWU
|
||||||
|
{
|
||||||
|
si5351bx_setfreq(2, frequency + sideTone);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updateDisplay();
|
|
||||||
|
//reduce latency time when begin of CW mode
|
||||||
|
if (isDisplayUpdate == 1)
|
||||||
|
updateDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopTx(){
|
void stopTx(){
|
||||||
inTx = 0;
|
inTx = 0;
|
||||||
|
|
||||||
digitalWrite(TX_RX, 0); //turn off the tx
|
digitalWrite(TX_RX, 0); //turn off the tx
|
||||||
si5351bx_setfreq(0, usbCarrier); //set back the carrier oscillator anyway, cw tx switches it off
|
|
||||||
|
if (cwMode == 0)
|
||||||
|
si5351bx_setfreq(0, usbCarrier + (isIFShift ? ifShiftValue : 0)); //set back the carrier oscillator anyway, cw tx switches it off
|
||||||
|
else
|
||||||
|
si5351bx_setfreq(0, cwmCarrier + (isIFShift ? ifShiftValue : 0)); //set back the carrier oscillator anyway, cw tx switches it off
|
||||||
|
|
||||||
if (ritOn)
|
if (ritOn)
|
||||||
setFrequency(ritRxFrequency);
|
setFrequency(ritRxFrequency);
|
||||||
|
else if (splitOn == 1) {
|
||||||
|
//vfo Change
|
||||||
|
if (vfoActive == VFO_B){
|
||||||
|
vfoActive = VFO_A;
|
||||||
|
frequency = vfoA;
|
||||||
|
byteToMode(vfoA_mode);
|
||||||
|
}
|
||||||
|
else if (vfoActive == VFO_A){
|
||||||
|
vfoActive = VFO_B;
|
||||||
|
frequency = vfoB;
|
||||||
|
byteToMode(vfoB_mode);
|
||||||
|
}
|
||||||
|
setFrequency(frequency);
|
||||||
|
} //end of else
|
||||||
else
|
else
|
||||||
setFrequency(frequency);
|
setFrequency(frequency);
|
||||||
|
|
||||||
@@ -355,7 +647,7 @@ void checkPTT(){
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (digitalRead(PTT) == 0 && inTx == 0){
|
if (digitalRead(PTT) == 0 && inTx == 0){
|
||||||
startTx(TX_SSB);
|
startTx(TX_SSB, 1);
|
||||||
delay(50); //debounce the PTT
|
delay(50); //debounce the PTT
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,8 +656,6 @@ void checkPTT(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void checkButton(){
|
void checkButton(){
|
||||||
int i, t1, t2, knob, new_knob;
|
|
||||||
|
|
||||||
//only if the button is pressed
|
//only if the button is pressed
|
||||||
if (!btnDown())
|
if (!btnDown())
|
||||||
return;
|
return;
|
||||||
@@ -374,66 +664,83 @@ void checkButton(){
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
doMenu();
|
doMenu();
|
||||||
|
|
||||||
//wait for the button to go up again
|
//wait for the button to go up again
|
||||||
while(btnDown())
|
while(btnDown()) {
|
||||||
delay(10);
|
delay(10);
|
||||||
|
Check_Cat(0);
|
||||||
|
}
|
||||||
delay(50);//debounce
|
delay(50);//debounce
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/************************************
|
||||||
* The tuning jumps by 50 Hz on each step when you tune slowly
|
Replace function by KD8CEC
|
||||||
* As you spin the encoder faster, the jump size also increases
|
prevent error controls
|
||||||
* This way, you can quickly move to another band by just spinning the
|
applied Threshold for reduct errors, dial Lock, dynamic Step
|
||||||
* tuning knob
|
*************************************/
|
||||||
*/
|
byte threshold = 2; //noe action for count
|
||||||
|
unsigned long lastEncInputtime = 0;
|
||||||
|
int encodedSumValue = 0;
|
||||||
|
unsigned long lastTunetime = 0; //if continous moving, skip threshold processing
|
||||||
|
byte lastMovedirection = 0; //0 : stop, 1 : cw, 2 : ccw
|
||||||
|
|
||||||
void doTuning(){
|
#define skipThresholdTime 100
|
||||||
int s;
|
#define encodeTimeOut 1000
|
||||||
|
|
||||||
|
void doTuningWithThresHold(){
|
||||||
|
int s = 0;
|
||||||
unsigned long prev_freq;
|
unsigned long prev_freq;
|
||||||
|
long incdecValue = 0;
|
||||||
|
|
||||||
s = enc_read();
|
if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) ||
|
||||||
if (s){
|
(vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02)))
|
||||||
prev_freq = frequency;
|
return;
|
||||||
|
|
||||||
if (s > 10)
|
|
||||||
frequency += 200000l;
|
|
||||||
if (s > 7)
|
|
||||||
frequency += 10000l;
|
|
||||||
else if (s > 4)
|
|
||||||
frequency += 1000l;
|
|
||||||
else if (s > 2)
|
|
||||||
frequency += 500;
|
|
||||||
else if (s > 0)
|
|
||||||
frequency += 50l;
|
|
||||||
else if (s > -2)
|
|
||||||
frequency -= 50l;
|
|
||||||
else if (s > -4)
|
|
||||||
frequency -= 500l;
|
|
||||||
else if (s > -7)
|
|
||||||
frequency -= 1000l;
|
|
||||||
else if (s > -9)
|
|
||||||
frequency -= 10000l;
|
|
||||||
else
|
|
||||||
frequency -= 200000l;
|
|
||||||
|
|
||||||
if (prev_freq < 10000000l && frequency > 10000000l)
|
|
||||||
isUSB = true;
|
|
||||||
|
|
||||||
if (prev_freq > 10000000l && frequency < 10000000l)
|
|
||||||
isUSB = false;
|
|
||||||
|
|
||||||
setFrequency(frequency);
|
if (isCWAutoMode == 0 || cwAutoDialType == 1)
|
||||||
updateDisplay();
|
s = enc_read();
|
||||||
|
|
||||||
|
//if time is exceeded, it is recognized as an error,
|
||||||
|
//ignore exists values, because of errors
|
||||||
|
if (s == 0) {
|
||||||
|
if (encodedSumValue != 0 && (millis() - encodeTimeOut) > lastEncInputtime)
|
||||||
|
encodedSumValue = 0;
|
||||||
|
|
||||||
|
lastMovedirection = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
lastEncInputtime = millis();
|
||||||
|
|
||||||
|
//for check moving direction
|
||||||
|
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)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
lastTunetime = millis();
|
||||||
|
|
||||||
|
//Valid Action without noise
|
||||||
|
encodedSumValue = 0;
|
||||||
|
|
||||||
|
prev_freq = frequency;
|
||||||
|
//incdecValue = tuningStep * s;
|
||||||
|
frequency += (arTuneStep[tuneStepIndex -1] * s * (s * s < 10 ? 1 : 3)); //appield weight (s is speed)
|
||||||
|
|
||||||
|
if (prev_freq < 10000000l && frequency > 10000000l)
|
||||||
|
isUSB = true;
|
||||||
|
|
||||||
|
if (prev_freq > 10000000l && frequency < 10000000l)
|
||||||
|
isUSB = false;
|
||||||
|
|
||||||
|
setFrequency(frequency);
|
||||||
|
updateDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RIT only steps back and forth by 100 hz at a time
|
* RIT only steps back and forth by 100 hz at a time
|
||||||
*/
|
*/
|
||||||
void doRIT(){
|
void doRIT(){
|
||||||
unsigned long newFreq;
|
|
||||||
|
|
||||||
int knob = enc_read();
|
int knob = enc_read();
|
||||||
unsigned long old_freq = frequency;
|
unsigned long old_freq = frequency;
|
||||||
|
|
||||||
@@ -448,6 +755,57 @@ void doRIT(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void doIFShift(){
|
||||||
|
int knob = enc_read();
|
||||||
|
unsigned long old_freq = frequency;
|
||||||
|
|
||||||
|
if (knob != 0)
|
||||||
|
{
|
||||||
|
if (knob < 0)
|
||||||
|
ifShiftValue -= 1l;
|
||||||
|
else if (knob > 0)
|
||||||
|
ifShiftValue += 1;
|
||||||
|
|
||||||
|
updateLine2Buffer(1);
|
||||||
|
setFrequency(frequency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
save Frequency and mode to eeprom
|
||||||
|
*/
|
||||||
|
void storeFrequencyAndMode(byte saveType)
|
||||||
|
{
|
||||||
|
//freqType : 0 Both (vfoA and vfoB), 1 : vfoA, 2 : vfoB
|
||||||
|
if (saveType == 0 || saveType == 1) //vfoA
|
||||||
|
{
|
||||||
|
if (vfoA != vfoA_eeprom) {
|
||||||
|
EEPROM.put(VFO_A, vfoA);
|
||||||
|
vfoA_eeprom = vfoA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vfoA_mode != vfoA_mode_eeprom) {
|
||||||
|
EEPROM.put(VFO_A_MODE, vfoA_mode);
|
||||||
|
vfoA_mode_eeprom = vfoA_mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveType == 0 || saveType == 2) //vfoB
|
||||||
|
{
|
||||||
|
if (vfoB != vfoB_eeprom) {
|
||||||
|
EEPROM.put(VFO_B, vfoB);
|
||||||
|
vfoB_eeprom = vfoB;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vfoB_mode != vfoB_mode_eeprom) {
|
||||||
|
EEPROM.put(VFO_B_MODE, vfoB_mode);
|
||||||
|
vfoB_mode_eeprom = vfoB_mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The settings are read from EEPROM. The first time around, the values may not be
|
* 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
|
* present or out of range, in this case, some intelligent defaults are copied into the
|
||||||
@@ -456,23 +814,223 @@ void doRIT(){
|
|||||||
void initSettings(){
|
void initSettings(){
|
||||||
//read the settings from the eeprom and restore them
|
//read the settings from the eeprom and restore them
|
||||||
//if the readings are off, then set defaults
|
//if the readings are off, then set defaults
|
||||||
|
//for original source Section ===========================
|
||||||
EEPROM.get(MASTER_CAL, calibration);
|
EEPROM.get(MASTER_CAL, calibration);
|
||||||
EEPROM.get(USB_CAL, usbCarrier);
|
EEPROM.get(USB_CAL, usbCarrier);
|
||||||
EEPROM.get(VFO_A, vfoA);
|
EEPROM.get(VFO_A, vfoA);
|
||||||
EEPROM.get(VFO_B, vfoB);
|
EEPROM.get(VFO_B, vfoB);
|
||||||
EEPROM.get(CW_SIDETONE, sideTone);
|
EEPROM.get(CW_SIDETONE, sideTone);
|
||||||
EEPROM.get(CW_SPEED, cwSpeed);
|
EEPROM.get(CW_SPEED, cwSpeed);
|
||||||
|
//End of original code
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
//Add Lines by KD8CEC
|
||||||
|
//for custom source Section =============================
|
||||||
|
//ID & Version Check from EEProm
|
||||||
|
//if found different firmware, erase eeprom (32
|
||||||
|
#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.
|
||||||
|
if (EEPROM.read(FIRMWAR_ID_ADDR) != 0x59 ||
|
||||||
|
EEPROM.read(FIRMWAR_ID_ADDR + 1) != 0x58 ||
|
||||||
|
EEPROM.read(FIRMWAR_ID_ADDR + 2) != 0x68 ) {
|
||||||
|
|
||||||
|
printLineF(1, F("Init EEProm..."));
|
||||||
|
//initial all eeprom
|
||||||
|
for (unsigned int i = 32; i < 1024; i++) //protect Master_cal, usb_cal
|
||||||
|
EEPROM.write(i, 0);
|
||||||
|
|
||||||
|
//Write Firmware ID
|
||||||
|
EEPROM.write(FIRMWAR_ID_ADDR, 0x59);
|
||||||
|
EEPROM.write(FIRMWAR_ID_ADDR + 1, 0x58);
|
||||||
|
EEPROM.write(FIRMWAR_ID_ADDR + 2, 0x68);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Version Write for Memory Management Software
|
||||||
|
if (EEPROM.read(VERSION_ADDRESS) != VERSION_NUM)
|
||||||
|
EEPROM.write(VERSION_ADDRESS, VERSION_NUM);
|
||||||
|
|
||||||
|
EEPROM.get(CW_CAL, cwmCarrier);
|
||||||
|
|
||||||
|
//for Save VFO_A_MODE to eeprom
|
||||||
|
//0: default, 1:not use, 2:LSB, 3:USB, 4:CW, 5:AM, 6:FM
|
||||||
|
EEPROM.get(VFO_A_MODE, vfoA_mode);
|
||||||
|
EEPROM.get(VFO_B_MODE, vfoB_mode);
|
||||||
|
|
||||||
|
//CW DelayTime
|
||||||
|
EEPROM.get(CW_DELAY, cwDelayTime);
|
||||||
|
|
||||||
|
//CW interval between TX and CW Start
|
||||||
|
EEPROM.get(CW_START, delayBeforeCWStartTime);
|
||||||
|
EEPROM.get(CW_KEY_TYPE, cwKeyType);
|
||||||
|
if (cwKeyType > 2)
|
||||||
|
cwKeyType = 0;
|
||||||
|
|
||||||
|
if (cwKeyType == 0)
|
||||||
|
Iambic_Key = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Iambic_Key = true;
|
||||||
|
if (cwKeyType == 1)
|
||||||
|
keyerControl &= ~IAMBICB;
|
||||||
|
else
|
||||||
|
keyerControl |= IAMBICB;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EEPROM.get(DISPLAY_OPTION1, displayOption1);
|
||||||
|
EEPROM.get(DISPLAY_OPTION2, displayOption2);
|
||||||
|
|
||||||
|
//User callsign information
|
||||||
|
if (EEPROM.read(USER_CALLSIGN_KEY) == 0x59)
|
||||||
|
userCallsignLength = EEPROM.read(USER_CALLSIGN_LEN); //MAXIMUM 18 LENGTH
|
||||||
|
|
||||||
|
//Ham Band Count
|
||||||
|
EEPROM.get(HAM_BAND_COUNT, useHamBandCount);
|
||||||
|
EEPROM.get(TX_TUNE_TYPE, tuneTXType);
|
||||||
|
|
||||||
|
byte findedValidValueCount = 0;
|
||||||
|
|
||||||
|
//Read band Information
|
||||||
|
for (byte i = 0; i < useHamBandCount; i++) {
|
||||||
|
unsigned int tmpReadValue = 0;
|
||||||
|
EEPROM.get(HAM_BAND_RANGE + 4 * i, tmpReadValue);
|
||||||
|
hamBandRange[i][0] = tmpReadValue;
|
||||||
|
|
||||||
|
if (tmpReadValue > 1 && tmpReadValue < 55000)
|
||||||
|
findedValidValueCount++;
|
||||||
|
|
||||||
|
EEPROM.get(HAM_BAND_RANGE + 4 * i + 2, tmpReadValue);
|
||||||
|
hamBandRange[i][1] = tmpReadValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check Value Range and default Set for new users
|
||||||
|
if ((3 < tuneTXType && tuneTXType < 100) || 103 < tuneTXType || useHamBandCount < 1 || findedValidValueCount < 5)
|
||||||
|
{
|
||||||
|
tuneTXType = 2;
|
||||||
|
//if empty band Information, auto insert default region 1 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[4][0] = 10100; hamBandRange[4][1] = 10150;
|
||||||
|
hamBandRange[5][0] = 14000; hamBandRange[5][1] = 14350;
|
||||||
|
hamBandRange[6][0] = 18068; hamBandRange[6][1] = 18168;
|
||||||
|
hamBandRange[7][0] = 21000; hamBandRange[7][1] = 21450;
|
||||||
|
hamBandRange[8][0] = 24890; hamBandRange[8][1] = 24990;
|
||||||
|
hamBandRange[9][0] = 28000; hamBandRange[9][1] = 29700;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Read Tuning Step Index, and steps
|
||||||
|
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
|
||||||
|
findedValidValueCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check Value Range and default Set for new users
|
||||||
|
if (findedValidValueCount < 5)
|
||||||
|
{
|
||||||
|
//Default Setting
|
||||||
|
arTuneStep[0] = 10;
|
||||||
|
arTuneStep[1] = 20;
|
||||||
|
arTuneStep[2] = 50;
|
||||||
|
arTuneStep[3] = 100;
|
||||||
|
arTuneStep[4] = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tuneStepIndex == 0) //New User
|
||||||
|
tuneStepIndex = 3;
|
||||||
|
|
||||||
|
//CW Key ADC Range ======= adjust set value for reduce cw keying error
|
||||||
|
//by KD8CEC
|
||||||
|
unsigned int tmpMostBits = 0;
|
||||||
|
tmpMostBits = EEPROM.read(CW_ADC_MOST_BIT1);
|
||||||
|
cwAdcSTFrom = EEPROM.read(CW_ADC_ST_FROM) | ((tmpMostBits & 0x03) << 8);
|
||||||
|
cwAdcSTTo = EEPROM.read(CW_ADC_ST_TO) | ((tmpMostBits & 0x0C) << 6);
|
||||||
|
cwAdcDotFrom = EEPROM.read(CW_ADC_DOT_FROM) | ((tmpMostBits & 0x30) << 4);
|
||||||
|
cwAdcDotTo = EEPROM.read(CW_ADC_DOT_TO) | ((tmpMostBits & 0xC0) << 2);
|
||||||
|
|
||||||
|
tmpMostBits = EEPROM.read(CW_ADC_MOST_BIT2);
|
||||||
|
cwAdcDashFrom = EEPROM.read(CW_ADC_DASH_FROM) | ((tmpMostBits & 0x03) << 8);
|
||||||
|
cwAdcDashTo = EEPROM.read(CW_ADC_DASH_TO) | ((tmpMostBits & 0x0C) << 6);
|
||||||
|
cwAdcBothFrom = EEPROM.read(CW_ADC_BOTH_FROM) | ((tmpMostBits & 0x30) << 4);
|
||||||
|
cwAdcBothTo = EEPROM.read(CW_ADC_BOTH_TO) | ((tmpMostBits & 0xC0) << 2);
|
||||||
|
|
||||||
|
//default Value (for original hardware)
|
||||||
|
if (cwAdcSTFrom >= cwAdcSTTo)
|
||||||
|
{
|
||||||
|
cwAdcSTFrom = 0;
|
||||||
|
cwAdcSTTo = 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cwAdcBothFrom >= cwAdcBothTo)
|
||||||
|
{
|
||||||
|
cwAdcBothFrom = 51;
|
||||||
|
cwAdcBothTo = 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cwAdcDotFrom >= cwAdcDotTo)
|
||||||
|
{
|
||||||
|
cwAdcDotFrom = 301;
|
||||||
|
cwAdcDotTo = 600;
|
||||||
|
}
|
||||||
|
if (cwAdcDashFrom >= cwAdcDashTo)
|
||||||
|
{
|
||||||
|
cwAdcDashFrom = 601;
|
||||||
|
cwAdcDashTo = 800;
|
||||||
|
}
|
||||||
|
//end of CW Keying Variables
|
||||||
|
|
||||||
|
if (cwDelayTime < 1 || cwDelayTime > 250)
|
||||||
|
cwDelayTime = 60;
|
||||||
|
|
||||||
|
if (vfoA_mode < 2)
|
||||||
|
vfoA_mode = 2;
|
||||||
|
|
||||||
|
if (vfoB_mode < 2)
|
||||||
|
vfoB_mode = 3;
|
||||||
|
|
||||||
|
//original code with modified by kd8cec
|
||||||
if (usbCarrier > 12010000l || usbCarrier < 11990000l)
|
if (usbCarrier > 12010000l || usbCarrier < 11990000l)
|
||||||
usbCarrier = 11997000l;
|
usbCarrier = 11995000l;
|
||||||
if (vfoA > 35000000l || 3500000l > vfoA)
|
|
||||||
|
if (cwmCarrier > 12010000l || cwmCarrier < 11990000l)
|
||||||
|
cwmCarrier = 11995000l;
|
||||||
|
|
||||||
|
if (vfoA > 35000000l || 3500000l > vfoA) {
|
||||||
vfoA = 7150000l;
|
vfoA = 7150000l;
|
||||||
if (vfoB > 35000000l || 3500000l > vfoB)
|
vfoA_mode = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vfoB > 35000000l || 3500000l > vfoB) {
|
||||||
vfoB = 14150000l;
|
vfoB = 14150000l;
|
||||||
|
vfoB_mode = 3;
|
||||||
|
}
|
||||||
|
//end of original code section
|
||||||
|
|
||||||
|
//for protect eeprom life by KD8CEC
|
||||||
|
vfoA_eeprom = vfoA;
|
||||||
|
vfoB_eeprom = vfoB;
|
||||||
|
vfoA_mode_eeprom = vfoA_mode;
|
||||||
|
vfoB_mode_eeprom = vfoB_mode;
|
||||||
|
|
||||||
if (sideTone < 100 || 2000 < sideTone)
|
if (sideTone < 100 || 2000 < sideTone)
|
||||||
sideTone = 800;
|
sideTone = 800;
|
||||||
if (cwSpeed < 10 || 1000 < cwSpeed)
|
if (cwSpeed < 10 || 1000 < cwSpeed)
|
||||||
cwSpeed = 100;
|
cwSpeed = 100;
|
||||||
|
|
||||||
|
if (sideTone < 300 || sideTone > 1000) {
|
||||||
|
sideTonePitch = 0;
|
||||||
|
sideToneSub = 0;;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
sideTonePitch = (sideTone - 300) / 50;
|
||||||
|
sideToneSub = sideTone % 50;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initPorts(){
|
void initPorts(){
|
||||||
@@ -490,6 +1048,7 @@ void initPorts(){
|
|||||||
|
|
||||||
pinMode(PTT, INPUT_PULLUP);
|
pinMode(PTT, INPUT_PULLUP);
|
||||||
pinMode(ANALOG_KEYER, INPUT_PULLUP);
|
pinMode(ANALOG_KEYER, INPUT_PULLUP);
|
||||||
|
pinMode(ANALOG_SMETER, INPUT); //by KD8CEC
|
||||||
|
|
||||||
pinMode(CW_TONE, OUTPUT);
|
pinMode(CW_TONE, OUTPUT);
|
||||||
digitalWrite(CW_TONE, 0);
|
digitalWrite(CW_TONE, 0);
|
||||||
@@ -510,21 +1069,45 @@ void initPorts(){
|
|||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
Serial.begin(9600);
|
/*
|
||||||
|
//Init EEProm for Fault EEProm TEST and Factory Reset
|
||||||
|
//please remove remark for others.
|
||||||
|
//for (int i = 0; i < 1024; i++)
|
||||||
|
for (int i = 16; i < 1024; i++) //protect Master_cal, usb_cal
|
||||||
|
EEPROM.write(i, 0xFF);
|
||||||
lcd.begin(16, 2);
|
lcd.begin(16, 2);
|
||||||
|
printLineF(1, F("Complete Erase"));
|
||||||
|
sleep(1000);
|
||||||
|
//while(1);
|
||||||
|
//end section of test
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Serial.begin(9600);
|
||||||
|
lcd.begin(16, 2);
|
||||||
|
printLineF(1, F("CECBT v0.33"));
|
||||||
|
|
||||||
//we print this line so this shows up even if the raduino
|
Init_Cat(38400, SERIAL_8N1);
|
||||||
//crashes later in the code
|
|
||||||
printLine1("uBITX v0.20");
|
|
||||||
delay(500);
|
|
||||||
|
|
||||||
initMeter(); //not used in this build
|
initMeter(); //not used in this build
|
||||||
initSettings();
|
initSettings();
|
||||||
|
|
||||||
|
if (userCallsignLength > 0 && ((userCallsignLength & 0x80) == 0x80)) {
|
||||||
|
userCallsignLength = userCallsignLength & 0x7F;
|
||||||
|
printLineFromEEPRom(0, 0, 0, userCallsignLength -1); //eeprom to lcd use offset (USER_CALLSIGN_DAT)
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printLineF(0, F("uBITX v0.20"));
|
||||||
|
delay(500);
|
||||||
|
clearLine2();
|
||||||
|
}
|
||||||
|
|
||||||
initPorts();
|
initPorts();
|
||||||
|
|
||||||
|
byteToMode(vfoA_mode);
|
||||||
initOscillators();
|
initOscillators();
|
||||||
|
|
||||||
frequency = vfoA;
|
frequency = vfoA;
|
||||||
|
saveCheckFreq = frequency; //for auto save frequency
|
||||||
setFrequency(vfoA);
|
setFrequency(vfoA);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
|
|
||||||
@@ -536,23 +1119,70 @@ void setup()
|
|||||||
/**
|
/**
|
||||||
* The loop checks for keydown, ptt, function button and tuning.
|
* The loop checks for keydown, ptt, function button and tuning.
|
||||||
*/
|
*/
|
||||||
|
//for debug
|
||||||
|
int dbgCnt = 0;
|
||||||
byte flasher = 0;
|
byte flasher = 0;
|
||||||
void loop(){
|
|
||||||
|
|
||||||
cwKeyer();
|
|
||||||
if (!txCAT)
|
|
||||||
checkPTT();
|
|
||||||
checkButton();
|
|
||||||
|
|
||||||
|
void checkAutoSaveFreqMode()
|
||||||
|
{
|
||||||
|
//when tx or ritOn, disable auto save
|
||||||
|
if (inTx || ritOn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//detect change frequency
|
||||||
|
if (saveCheckFreq != frequency)
|
||||||
|
{
|
||||||
|
saveCheckTime = millis();
|
||||||
|
saveCheckFreq = frequency;
|
||||||
|
}
|
||||||
|
else if (saveCheckTime != 0)
|
||||||
|
{
|
||||||
|
//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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
if (isCWAutoMode == 0){ //when CW AutoKey Mode, disable this process
|
||||||
|
if (!txCAT)
|
||||||
|
checkPTT();
|
||||||
|
checkButton();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
controlAutoCW();
|
||||||
|
|
||||||
|
cwKeyer();
|
||||||
|
|
||||||
//tune only when not tranmsitting
|
//tune only when not tranmsitting
|
||||||
if (!inTx){
|
if (!inTx){
|
||||||
if (ritOn)
|
if (ritOn)
|
||||||
doRIT();
|
doRIT();
|
||||||
|
//else if (isIFShift)
|
||||||
|
// doIFShift();
|
||||||
else
|
else
|
||||||
doTuning();
|
doTuningWithThresHold();
|
||||||
}
|
|
||||||
|
if (isCWAutoMode == 0 && beforeIdle_ProcessTime < millis() - 250) {
|
||||||
|
idle_process();
|
||||||
|
beforeIdle_ProcessTime = millis();
|
||||||
|
}
|
||||||
|
} //end of check TX Status
|
||||||
|
|
||||||
//we check CAT after the encoder as it might put the radio into TX
|
//we check CAT after the encoder as it might put the radio into TX
|
||||||
checkCAT();
|
Check_Cat(inTx? 1 : 0);
|
||||||
|
checkAutoSaveFreqMode();
|
||||||
}
|
}
|
||||||
|
@@ -1,231 +0,0 @@
|
|||||||
/**
|
|
||||||
* The CAT protocol is used by many radios to provide remote control to comptuers through
|
|
||||||
* the serial port.
|
|
||||||
*
|
|
||||||
* This is very much a work in progress. Parts of this code have been liberally
|
|
||||||
* borrowed from other GPLicensed works like hamlib.
|
|
||||||
*
|
|
||||||
* WARNING : This is an unstable version and it has worked with fldigi,
|
|
||||||
* it gives time out error with WSJTX 1.8.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The next 4 functions are needed to implement the CAT protocol, which
|
|
||||||
// uses 4-bit BCD formatting.
|
|
||||||
//
|
|
||||||
byte setHighNibble(byte b,byte v) {
|
|
||||||
// Clear the high nibble
|
|
||||||
b &= 0x0f;
|
|
||||||
// Set the high nibble
|
|
||||||
return b | ((v & 0x0f) << 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte setLowNibble(byte b,byte v) {
|
|
||||||
// Clear the low nibble
|
|
||||||
b &= 0xf0;
|
|
||||||
// Set the low nibble
|
|
||||||
return b | (v & 0x0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getHighNibble(byte b) {
|
|
||||||
return (b >> 4) & 0x0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getLowNibble(byte b) {
|
|
||||||
return b & 0x0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Takes a number and produces the requested number of decimal digits, staring
|
|
||||||
// from the least significant digit.
|
|
||||||
//
|
|
||||||
void getDecimalDigits(unsigned long number,byte* result,int digits) {
|
|
||||||
for (int i = 0; i < digits; i++) {
|
|
||||||
// "Mask off" (in a decimal sense) the LSD and return it
|
|
||||||
result[i] = number % 10;
|
|
||||||
// "Shift right" (in a decimal sense)
|
|
||||||
number /= 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Takes a frequency and writes it into the CAT command buffer in BCD form.
|
|
||||||
//
|
|
||||||
void writeFreq(unsigned long freq,byte* cmd) {
|
|
||||||
// Convert the frequency to a set of decimal digits. We are taking 9 digits
|
|
||||||
// so that we can get up to 999 MHz. But the protocol doesn't care about the
|
|
||||||
// LSD (1's place), so we ignore that digit.
|
|
||||||
byte digits[9];
|
|
||||||
getDecimalDigits(freq,digits,9);
|
|
||||||
// Start from the LSB and get each nibble
|
|
||||||
cmd[3] = setLowNibble(cmd[3],digits[1]);
|
|
||||||
cmd[3] = setHighNibble(cmd[3],digits[2]);
|
|
||||||
cmd[2] = setLowNibble(cmd[2],digits[3]);
|
|
||||||
cmd[2] = setHighNibble(cmd[2],digits[4]);
|
|
||||||
cmd[1] = setLowNibble(cmd[1],digits[5]);
|
|
||||||
cmd[1] = setHighNibble(cmd[1],digits[6]);
|
|
||||||
cmd[0] = setLowNibble(cmd[0],digits[7]);
|
|
||||||
cmd[0] = setHighNibble(cmd[0],digits[8]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function takes a frquency that is encoded using 4 bytes of BCD
|
|
||||||
// representation and turns it into an long measured in Hz.
|
|
||||||
//
|
|
||||||
// [12][34][56][78] = 123.45678? Mhz
|
|
||||||
//
|
|
||||||
unsigned long readFreq(byte* cmd) {
|
|
||||||
// Pull off each of the digits
|
|
||||||
byte d7 = getHighNibble(cmd[0]);
|
|
||||||
byte d6 = getLowNibble(cmd[0]);
|
|
||||||
byte d5 = getHighNibble(cmd[1]);
|
|
||||||
byte d4 = getLowNibble(cmd[1]);
|
|
||||||
byte d3 = getHighNibble(cmd[2]);
|
|
||||||
byte d2 = getLowNibble(cmd[2]);
|
|
||||||
byte d1 = getHighNibble(cmd[3]);
|
|
||||||
byte d0 = getLowNibble(cmd[3]);
|
|
||||||
return
|
|
||||||
(unsigned long)d7 * 100000000L +
|
|
||||||
(unsigned long)d6 * 10000000L +
|
|
||||||
(unsigned long)d5 * 1000000L +
|
|
||||||
(unsigned long)d4 * 100000L +
|
|
||||||
(unsigned long)d3 * 10000L +
|
|
||||||
(unsigned long)d2 * 1000L +
|
|
||||||
(unsigned long)d1 * 100L +
|
|
||||||
(unsigned long)d0 * 10L;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Responds to all the cat commands, emulates FT-817
|
|
||||||
*/
|
|
||||||
|
|
||||||
void processCATCommand(byte* cmd) {
|
|
||||||
byte response[5];
|
|
||||||
|
|
||||||
// Debugging code, enable it to fix the cat implementation
|
|
||||||
|
|
||||||
count++;
|
|
||||||
if (cmd[4] == 0x00){
|
|
||||||
response[0]=0;
|
|
||||||
Serial.write(response, 1);
|
|
||||||
}
|
|
||||||
else if (cmd[4] == 0x01) {
|
|
||||||
unsigned long f = readFreq(cmd);
|
|
||||||
setFrequency(f);
|
|
||||||
updateDisplay();
|
|
||||||
//sprintf(b, "set:%ld", f);
|
|
||||||
//printLine2(b);
|
|
||||||
|
|
||||||
}
|
|
||||||
// Get frequency
|
|
||||||
else if (cmd[4] == 0x03){
|
|
||||||
writeFreq(frequency,response); // Put the frequency into the buffer
|
|
||||||
if (isUSB)
|
|
||||||
response[4] = 0x01; //USB
|
|
||||||
else
|
|
||||||
response[4] = 0x00; //LSB
|
|
||||||
Serial.write(response,5);
|
|
||||||
printLine2("cat:getfreq");
|
|
||||||
}
|
|
||||||
else if (cmd[4] == 0x07){ // set mode
|
|
||||||
if (cmd[0] == 0x00 || cmd[0] == 0x03)
|
|
||||||
isUSB = 0;
|
|
||||||
else
|
|
||||||
isUSB = 1;
|
|
||||||
response[0] = 0x00;
|
|
||||||
Serial.write(response, 1);
|
|
||||||
setFrequency(frequency);
|
|
||||||
//printLine2("cat: mode changed");
|
|
||||||
//updateDisplay();
|
|
||||||
}
|
|
||||||
else if (cmd[4] == 0x88){
|
|
||||||
if (inTx){
|
|
||||||
stopTx();
|
|
||||||
txCAT = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
response[0] = 0xf0;
|
|
||||||
printLine2("tx > rx");
|
|
||||||
Serial.write(response,1);
|
|
||||||
}
|
|
||||||
else if (cmd[4] == 0x08) { // PTT On
|
|
||||||
if (!inTx) {
|
|
||||||
response[0] = 0;
|
|
||||||
txCAT = true;
|
|
||||||
startTx(TX_SSB);
|
|
||||||
updateDisplay();
|
|
||||||
} else {
|
|
||||||
response[0] = 0xf0;
|
|
||||||
}
|
|
||||||
Serial.write(response,1);
|
|
||||||
printLine2("rx > tx");
|
|
||||||
}
|
|
||||||
// Read TX keyed state
|
|
||||||
else if (cmd[4] == 0x10) {
|
|
||||||
if (!inTx) {
|
|
||||||
response[0] = 0;
|
|
||||||
} else {
|
|
||||||
response[0] = 0xf0;
|
|
||||||
}
|
|
||||||
Serial.write(response,1);
|
|
||||||
printLine2("cat;0x10");
|
|
||||||
}
|
|
||||||
// PTT Off
|
|
||||||
else if (cmd[4] == 0x88) {
|
|
||||||
byte resBuf[0];
|
|
||||||
if (inTx) {
|
|
||||||
response[0] = 0;
|
|
||||||
} else {
|
|
||||||
response[0] = 0xf0;
|
|
||||||
}
|
|
||||||
Serial.write(response,1);
|
|
||||||
printLine2("cat;0x88");
|
|
||||||
//keyed = false;
|
|
||||||
//digitalWrite(13,LOW);
|
|
||||||
}
|
|
||||||
// Read receiver status
|
|
||||||
else if (cmd[4] == 0xe7) {
|
|
||||||
response[0] = 0x09;
|
|
||||||
Serial.write(response,1);
|
|
||||||
printLine2("cat;0xe7");
|
|
||||||
}
|
|
||||||
else if (cmd[4] == 0xf5){
|
|
||||||
|
|
||||||
}
|
|
||||||
// Read receiver status
|
|
||||||
else if (cmd[4] == 0xf7) {
|
|
||||||
response[0] = 0x00;
|
|
||||||
if (inTx) {
|
|
||||||
response[0] = response[0] | 0xf0;
|
|
||||||
}
|
|
||||||
Serial.write(response,1);
|
|
||||||
printLine2("cat;0xf7");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//somehow, get this to print the four bytes
|
|
||||||
ultoa(*((unsigned long *)cmd), c, 16);
|
|
||||||
itoa(cmd[4], b, 16);
|
|
||||||
strcat(b, ":");
|
|
||||||
strcat(b, c);
|
|
||||||
printLine2(b);
|
|
||||||
response[0] = 0x00;
|
|
||||||
Serial.write(response[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void checkCAT(){
|
|
||||||
static byte cat[5];
|
|
||||||
byte i;
|
|
||||||
|
|
||||||
if (Serial.available() < 5)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cat[4] = cat[3];
|
|
||||||
cat[3] = cat[2];
|
|
||||||
cat[2] = cat[0];
|
|
||||||
for (i = 0; i < 5; i++)
|
|
||||||
cat[i] = Serial.read();
|
|
||||||
|
|
||||||
processCATCommand(cat);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@@ -14,6 +14,7 @@ void btnWaitForClick(){
|
|||||||
void factory_alignment(){
|
void factory_alignment(){
|
||||||
|
|
||||||
factoryCalibration(1);
|
factoryCalibration(1);
|
||||||
|
line2DisplayStatus = 1;
|
||||||
|
|
||||||
if (calibration == 0){
|
if (calibration == 0){
|
||||||
printLine2("Setup Aborted");
|
printLine2("Setup Aborted");
|
||||||
@@ -36,6 +37,7 @@ void factory_alignment(){
|
|||||||
|
|
||||||
|
|
||||||
printLine2("#3:Test 3.5MHz");
|
printLine2("#3:Test 3.5MHz");
|
||||||
|
cwMode = 0;
|
||||||
isUSB = false;
|
isUSB = false;
|
||||||
setFrequency(3500000l);
|
setFrequency(3500000l);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
@@ -58,6 +60,7 @@ void factory_alignment(){
|
|||||||
btnWaitForClick();
|
btnWaitForClick();
|
||||||
printLine2("#5:Test 14MHz");
|
printLine2("#5:Test 14MHz");
|
||||||
|
|
||||||
|
cwMode = 0;
|
||||||
isUSB = true;
|
isUSB = true;
|
||||||
setFrequency(14000000l);
|
setFrequency(14000000l);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
@@ -79,6 +82,7 @@ void factory_alignment(){
|
|||||||
printLine2("Alignment done");
|
printLine2("Alignment done");
|
||||||
delay(1000);
|
delay(1000);
|
||||||
|
|
||||||
|
cwMode = 0;
|
||||||
isUSB = false;
|
isUSB = false;
|
||||||
setFrequency(7150000l);
|
setFrequency(7150000l);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
|
237
ubitx_20/ubitx_idle.ino
Normal file
237
ubitx_20/ubitx_idle.ino
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
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
|
||||||
|
//immediate execution, not call by scheulder
|
||||||
|
void updateLine2Buffer(char isDirectCall)
|
||||||
|
{
|
||||||
|
unsigned long tmpFreq = 0;
|
||||||
|
if (isDirectCall == 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] = ' ';
|
||||||
|
} //check direct call by encoder
|
||||||
|
|
||||||
|
|
||||||
|
if (isIFShift)
|
||||||
|
{
|
||||||
|
if (isDirectCall == 1)
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
line2Buffer[i] = ' ';
|
||||||
|
|
||||||
|
//IFShift Offset Value
|
||||||
|
line2Buffer[8] = 'I';
|
||||||
|
line2Buffer[9] = 'F';
|
||||||
|
|
||||||
|
if (ifShiftValue == 0)
|
||||||
|
{
|
||||||
|
line2Buffer[10] = 'S';
|
||||||
|
line2Buffer[11] = ':';
|
||||||
|
line2Buffer[12] = 'O';
|
||||||
|
line2Buffer[13] = 'F';
|
||||||
|
line2Buffer[14] = 'F';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0;
|
||||||
|
line2Buffer[11] = 0;
|
||||||
|
line2Buffer[12] = ' ';
|
||||||
|
|
||||||
|
//11, 12, 13, 14, 15
|
||||||
|
memset(b, 0, sizeof(b));
|
||||||
|
ltoa(ifShiftValue, b, DEC);
|
||||||
|
strncat(line2Buffer, b, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDirectCall == 1) //if call by encoder (not scheduler), immediate print value
|
||||||
|
printLine2(line2Buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isDirectCall != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//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';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//meterType : 0 = S.Meter, 1 : P.Meter
|
||||||
|
void DisplayMeter(byte meterType, byte meterValue, char drawPosition)
|
||||||
|
{
|
||||||
|
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 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;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -1,6 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* CW Keyer
|
CW Keyer
|
||||||
*
|
CW Key logic change with ron's code (ubitx_keyer.cpp)
|
||||||
|
Ron's logic has been modified to work with the original uBITX by KD8CEC
|
||||||
|
|
||||||
|
Original Comment ----------------------------------------------------------------------------
|
||||||
* The CW keyer handles either a straight key or an iambic / paddle key.
|
* The CW keyer handles either a straight key or an iambic / paddle key.
|
||||||
* They all use just one analog input line. This is how it works.
|
* They all use just one analog input line. This is how it works.
|
||||||
* The analog line has the internal pull-up resistor enabled.
|
* The analog line has the internal pull-up resistor enabled.
|
||||||
@@ -23,7 +26,7 @@
|
|||||||
|
|
||||||
|
|
||||||
// in milliseconds, this is the parameter that determines how long the tx will hold between cw key downs
|
// in milliseconds, this is the parameter that determines how long the tx will hold between cw key downs
|
||||||
#define CW_TIMEOUT (600l)
|
//#define CW_TIMEOUT (600l) //Change to CW Delaytime for value save to eeprom
|
||||||
#define PADDLE_DOT 1
|
#define PADDLE_DOT 1
|
||||||
#define PADDLE_DASH 2
|
#define PADDLE_DASH 2
|
||||||
#define PADDLE_BOTH 3
|
#define PADDLE_BOTH 3
|
||||||
@@ -34,7 +37,6 @@
|
|||||||
//when both are simultaneously pressed
|
//when both are simultaneously pressed
|
||||||
char lastPaddle = 0;
|
char lastPaddle = 0;
|
||||||
|
|
||||||
|
|
||||||
//reads the analog keyer pin and reports the paddle
|
//reads the analog keyer pin and reports the paddle
|
||||||
byte getPaddle(){
|
byte getPaddle(){
|
||||||
int paddle = analogRead(ANALOG_KEYER);
|
int paddle = analogRead(ANALOG_KEYER);
|
||||||
@@ -61,7 +63,10 @@ void cwKeydown(){
|
|||||||
keyDown = 1; //tracks the CW_KEY
|
keyDown = 1; //tracks the CW_KEY
|
||||||
tone(CW_TONE, (int)sideTone);
|
tone(CW_TONE, (int)sideTone);
|
||||||
digitalWrite(CW_KEY, 1);
|
digitalWrite(CW_KEY, 1);
|
||||||
cwTimeout = millis() + CW_TIMEOUT;
|
|
||||||
|
//Modified by KD8CEC, for CW Delay Time save to eeprom
|
||||||
|
//cwTimeout = millis() + CW_TIMEOUT;
|
||||||
|
cwTimeout = millis() + cwDelayTime * 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,16 +77,187 @@ void cwKeyUp(){
|
|||||||
keyDown = 0; //tracks the CW_KEY
|
keyDown = 0; //tracks the CW_KEY
|
||||||
noTone(CW_TONE);
|
noTone(CW_TONE);
|
||||||
digitalWrite(CW_KEY, 0);
|
digitalWrite(CW_KEY, 0);
|
||||||
cwTimeout = millis() + CW_TIMEOUT;
|
|
||||||
|
//Modified by KD8CEC, for CW Delay Time save to eeprom
|
||||||
|
//cwTimeout = millis() + CW_TIMEOUT;
|
||||||
|
cwTimeout = millis() + cwDelayTime * 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Variables for Ron's new logic
|
||||||
|
#define DIT_L 0x01 // DIT latch
|
||||||
|
#define DAH_L 0x02 // DAH latch
|
||||||
|
#define DIT_PROC 0x04 // DIT is being processed
|
||||||
|
#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;
|
||||||
|
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;
|
||||||
|
int paddle = analogRead(ANALOG_KEYER);
|
||||||
|
|
||||||
|
if (paddle >= cwAdcDashFrom && paddle <= cwAdcDashTo)
|
||||||
|
tmpKeyerControl |= DAH_L;
|
||||||
|
else if (paddle >= cwAdcDotFrom && paddle <= cwAdcDotTo)
|
||||||
|
tmpKeyerControl |= DIT_L;
|
||||||
|
else if (paddle >= cwAdcBothFrom && paddle <= cwAdcBothTo)
|
||||||
|
tmpKeyerControl |= (DAH_L | DIT_L) ;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Iambic_Key)
|
||||||
|
tmpKeyerControl = 0 ;
|
||||||
|
else if (paddle >= cwAdcSTFrom && paddle <= cwAdcSTTo)
|
||||||
|
tmpKeyerControl = DIT_L ;
|
||||||
|
else
|
||||||
|
tmpKeyerControl = 0 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUpdateKeyState == 1)
|
||||||
|
keyerControl |= tmpKeyerControl;
|
||||||
|
|
||||||
|
return tmpKeyerControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
// New logic, by RON
|
||||||
|
// modified by KD8CEC
|
||||||
|
******************************************************************************/
|
||||||
|
void cwKeyer(void){
|
||||||
|
byte paddle;
|
||||||
|
lastPaddle = 0;
|
||||||
|
int dot,dash;
|
||||||
|
bool continue_loop = true;
|
||||||
|
unsigned tmpKeyControl = 0;
|
||||||
|
|
||||||
|
if( Iambic_Key ) {
|
||||||
|
while(continue_loop) {
|
||||||
|
switch (keyerState) {
|
||||||
|
case IDLE:
|
||||||
|
tmpKeyControl = update_PaddleLatch(0);
|
||||||
|
if ( tmpKeyControl == DAH_L || tmpKeyControl == DIT_L ||
|
||||||
|
tmpKeyControl == (DAH_L | DIT_L) || (keyerControl & 0x03)) {
|
||||||
|
update_PaddleLatch(1);
|
||||||
|
keyerState = CHK_DIT;
|
||||||
|
}else{
|
||||||
|
if (0 < cwTimeout && cwTimeout < millis()){
|
||||||
|
cwTimeout = 0;
|
||||||
|
stopTx();
|
||||||
|
}
|
||||||
|
continue_loop = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CHK_DIT:
|
||||||
|
if (keyerControl & DIT_L) {
|
||||||
|
keyerControl |= DIT_PROC;
|
||||||
|
ktimer = cwSpeed;
|
||||||
|
keyerState = KEYED_PREP;
|
||||||
|
}else{
|
||||||
|
keyerState = CHK_DAH;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CHK_DAH:
|
||||||
|
if (keyerControl & DAH_L) {
|
||||||
|
ktimer = cwSpeed*3;
|
||||||
|
keyerState = KEYED_PREP;
|
||||||
|
}else{
|
||||||
|
keyerState = IDLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEYED_PREP:
|
||||||
|
ktimer += millis(); // set ktimer to interval end time
|
||||||
|
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
||||||
|
keyerState = KEYED; // next state
|
||||||
|
if (!inTx){
|
||||||
|
keyDown = 0;
|
||||||
|
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
||||||
|
startTx(TX_CW, 1);
|
||||||
|
}
|
||||||
|
cwKeydown();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEYED:
|
||||||
|
if (millis() > ktimer) { // are we at end of key down ?
|
||||||
|
cwKeyUp();
|
||||||
|
ktimer = millis() + cwSpeed; // inter-element time
|
||||||
|
keyerState = INTER_ELEMENT; // next state
|
||||||
|
}else if (keyerControl & IAMBICB) {
|
||||||
|
update_PaddleLatch(1); // early paddle latch in Iambic B mode
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INTER_ELEMENT:
|
||||||
|
// Insert time between dits/dahs
|
||||||
|
update_PaddleLatch(1); // latch paddle state
|
||||||
|
if (millis() > ktimer) { // are we at end of inter-space ?
|
||||||
|
if (keyerControl & DIT_PROC) { // was it a dit or dah ?
|
||||||
|
keyerControl &= ~(DIT_L + DIT_PROC); // clear two bits
|
||||||
|
keyerState = CHK_DAH; // dit done, check for dah
|
||||||
|
}else{
|
||||||
|
keyerControl &= ~(DAH_L); // clear dah latch
|
||||||
|
keyerState = IDLE; // go idle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Check_Cat(3);
|
||||||
|
} //end of while
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
while(1){
|
||||||
|
if (update_PaddleLatch(0) == DIT_L) {
|
||||||
|
// if we are here, it is only because the key is pressed
|
||||||
|
if (!inTx){
|
||||||
|
keyDown = 0;
|
||||||
|
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
||||||
|
startTx(TX_CW, 1);
|
||||||
|
}
|
||||||
|
cwKeydown();
|
||||||
|
|
||||||
|
while ( update_PaddleLatch(0) == DIT_L )
|
||||||
|
delay_background(1, 3);
|
||||||
|
|
||||||
|
cwKeyUp();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (0 < cwTimeout && cwTimeout < millis()){
|
||||||
|
cwTimeout = 0;
|
||||||
|
keyDown = 0;
|
||||||
|
stopTx();
|
||||||
|
}
|
||||||
|
if (!cwTimeout)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Check_Cat(2);
|
||||||
|
} //end of while
|
||||||
|
} //end of elese
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=======================================================================================
|
||||||
|
//Before logic
|
||||||
|
//by Farhan and modified by KD8CEC
|
||||||
|
//======================================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The keyer handles the straight key as well as the iambic key
|
* The keyer handles the straight key as well as the iambic key
|
||||||
* This module keeps looping until the user stops sending cw
|
* This module keeps looping until the user stops sending cw
|
||||||
* if the cwTimeout is set to 0, then it means, we have to exit the keyer loop
|
* if the cwTimeout is set to 0, then it means, we have to exit the keyer loop
|
||||||
* Each time the key is hit the cwTimeout is pushed to a time in the future by cwKeyDown()
|
* Each time the key is hit the cwTimeout is pushed to a time in the future by cwKeyDown()
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
void cwKeyer(){
|
void cwKeyer(){
|
||||||
byte paddle;
|
byte paddle;
|
||||||
lastPaddle = 0;
|
lastPaddle = 0;
|
||||||
@@ -92,6 +268,10 @@ void cwKeyer(){
|
|||||||
// do nothing if the paddle has not been touched, unless
|
// do nothing if the paddle has not been touched, unless
|
||||||
// we are in the cw mode and we have timed out
|
// we are in the cw mode and we have timed out
|
||||||
if (!paddle){
|
if (!paddle){
|
||||||
|
//modifed by KD8CEC for auto CW Send
|
||||||
|
if (isCWAutoMode > 1) //if while auto cw sending, dont stop tx by paddle position
|
||||||
|
return;
|
||||||
|
|
||||||
if (0 < cwTimeout && cwTimeout < millis()){
|
if (0 < cwTimeout && cwTimeout < millis()){
|
||||||
cwTimeout = 0;
|
cwTimeout = 0;
|
||||||
keyDown = 0;
|
keyDown = 0;
|
||||||
@@ -101,50 +281,61 @@ void cwKeyer(){
|
|||||||
if (!cwTimeout)
|
if (!cwTimeout)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//if a paddle was used (not a straight key) we should extend the space to be a full dash
|
Check_Cat(2); //for uBITX on Raspberry pi, when straight keying, disconnect / test complete
|
||||||
//by adding two more dots long space (one has already been added at the end of the dot or dash)
|
|
||||||
if (cwTimeout > 0 && lastPaddle != PADDLE_STRAIGHT)
|
|
||||||
delay(cwSpeed * 2);
|
|
||||||
|
|
||||||
// got back to the begining of the loop, if no further activity happens on the paddle or the straight key
|
|
||||||
// we will time out, and return out of this routine
|
|
||||||
delay(5);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.print("paddle:");Serial.println(paddle);
|
//if while auto cw send, stop auto cw
|
||||||
|
//but isAutoCWHold for Manual Keying with cwAutoSend
|
||||||
|
if (isCWAutoMode > 1 && isAutoCWHold == 0)
|
||||||
|
isCWAutoMode = 1; //read status
|
||||||
|
|
||||||
|
//Remoark Debug code / Serial Use by CAT Protocol
|
||||||
|
//Serial.print("paddle:");Serial.println(paddle);
|
||||||
// if we are here, it is only because the key or the paddle is pressed
|
// if we are here, it is only because the key or the paddle is pressed
|
||||||
if (!inTx){
|
if (!inTx){
|
||||||
keyDown = 0;
|
keyDown = 0;
|
||||||
cwTimeout = millis() + CW_TIMEOUT;
|
//Modified by KD8CEC, for CW Delay Time save to eeprom
|
||||||
startTx(TX_CW);
|
//cwTimeout = millis() + CW_TIMEOUT;
|
||||||
|
cwTimeout = millis() + cwDelayTime * 10;
|
||||||
|
|
||||||
|
startTx(TX_CW, 0); //disable updateDisplay Command for reduce latency time
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
|
|
||||||
|
//DelayTime Option
|
||||||
|
delay_background(delayBeforeCWStartTime * 2, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// star the transmission)
|
// star the transmission)
|
||||||
// we store the transmitted character in the lastPaddle
|
// we store the transmitted character in the lastPaddle
|
||||||
cwKeydown();
|
cwKeydown();
|
||||||
if (paddle == PADDLE_DOT){
|
if (paddle == PADDLE_DOT){
|
||||||
delay(cwSpeed);
|
//delay(cwSpeed);
|
||||||
|
delay_background(cwSpeed, 3);
|
||||||
lastPaddle = PADDLE_DOT;
|
lastPaddle = PADDLE_DOT;
|
||||||
}
|
}
|
||||||
else if (paddle == PADDLE_DASH){
|
else if (paddle == PADDLE_DASH){
|
||||||
delay(cwSpeed * 3);
|
//delay(cwSpeed * 3);
|
||||||
|
delay_background(cwSpeed * 3, 3);
|
||||||
lastPaddle = PADDLE_DASH;
|
lastPaddle = PADDLE_DASH;
|
||||||
}
|
}
|
||||||
else if (paddle == PADDLE_BOTH){ //both paddles down
|
else if (paddle == PADDLE_BOTH){ //both paddles down
|
||||||
//depending upon what was sent last, send the other
|
//depending upon what was sent last, send the other
|
||||||
if (lastPaddle == PADDLE_DOT) {
|
if (lastPaddle == PADDLE_DOT) {
|
||||||
delay(cwSpeed * 3);
|
//delay(cwSpeed * 3);
|
||||||
|
delay_background(cwSpeed * 3, 3);
|
||||||
lastPaddle = PADDLE_DASH;
|
lastPaddle = PADDLE_DASH;
|
||||||
}else{
|
}else{
|
||||||
delay(cwSpeed);
|
//delay(cwSpeed);
|
||||||
|
delay_background(cwSpeed, 3);
|
||||||
lastPaddle = PADDLE_DOT;
|
lastPaddle = PADDLE_DOT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (paddle == PADDLE_STRAIGHT){
|
else if (paddle == PADDLE_STRAIGHT){
|
||||||
while (getPaddle() == PADDLE_STRAIGHT)
|
while (getPaddle() == PADDLE_STRAIGHT) {
|
||||||
delay(1);
|
delay(1);
|
||||||
|
Check_Cat(2);
|
||||||
|
}
|
||||||
lastPaddle = PADDLE_STRAIGHT;
|
lastPaddle = PADDLE_STRAIGHT;
|
||||||
}
|
}
|
||||||
cwKeyUp();
|
cwKeyUp();
|
||||||
@@ -153,3 +344,6 @@ void cwKeyer(){
|
|||||||
delay(cwSpeed);
|
delay(cwSpeed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -62,7 +62,7 @@ void i2cWriten(uint8_t reg, uint8_t *vals, uint8_t vcnt) { // write array
|
|||||||
|
|
||||||
|
|
||||||
void si5351bx_init() { // Call once at power-up, start PLLA
|
void si5351bx_init() { // Call once at power-up, start PLLA
|
||||||
uint8_t reg; uint32_t msxp1;
|
uint32_t msxp1;
|
||||||
Wire.begin();
|
Wire.begin();
|
||||||
i2cWrite(149, 0); // SpreadSpectrum off
|
i2cWrite(149, 0); // SpreadSpectrum off
|
||||||
i2cWrite(3, si5351bx_clken); // Disable all CLK output drivers
|
i2cWrite(3, si5351bx_clken); // Disable all CLK output drivers
|
||||||
@@ -109,7 +109,11 @@ void initOscillators(){
|
|||||||
//initialize the SI5351
|
//initialize the SI5351
|
||||||
si5351bx_init();
|
si5351bx_init();
|
||||||
si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + calibration; // apply the calibration correction factor
|
si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + calibration; // apply the calibration correction factor
|
||||||
si5351bx_setfreq(0, usbCarrier);
|
|
||||||
|
if (cwMode == 0)
|
||||||
|
si5351bx_setfreq(0, usbCarrier + (isIFShift ? ifShiftValue : 0));
|
||||||
|
else
|
||||||
|
si5351bx_setfreq(0, cwmCarrier + (isIFShift ? ifShiftValue : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -5,6 +5,8 @@
|
|||||||
* of the radio. Occasionally, it is used to provide a two-line information that is
|
* of the radio. Occasionally, it is used to provide a two-line information that is
|
||||||
* quickly cleared up.
|
* quickly cleared up.
|
||||||
*/
|
*/
|
||||||
|
//#define printLineF1(x) (printLineF(1, x))
|
||||||
|
//#define printLineF2(x) (printLineF(0, x))
|
||||||
|
|
||||||
//returns true if the button is pressed
|
//returns true if the button is pressed
|
||||||
int btnDown(){
|
int btnDown(){
|
||||||
@@ -23,9 +25,9 @@ int btnDown(){
|
|||||||
* The current reading of the meter is assembled in the string called meter
|
* The current reading of the meter is assembled in the string called meter
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char meter[17];
|
|
||||||
|
|
||||||
byte s_meter_bitmap[] = {
|
/*
|
||||||
|
const PROGMEM uint8_t s_meter_bitmap[] = {
|
||||||
B00000,B00000,B00000,B00000,B00000,B00100,B00100,B11011,
|
B00000,B00000,B00000,B00000,B00000,B00100,B00100,B11011,
|
||||||
B10000,B10000,B10000,B10000,B10100,B10100,B10100,B11011,
|
B10000,B10000,B10000,B10000,B10100,B10100,B10100,B11011,
|
||||||
B01000,B01000,B01000,B01000,B01100,B01100,B01100,B11011,
|
B01000,B01000,B01000,B01000,B01100,B01100,B01100,B11011,
|
||||||
@@ -33,26 +35,92 @@ byte s_meter_bitmap[] = {
|
|||||||
B00010,B00010,B00010,B00010,B00110,B00110,B00110,B11011,
|
B00010,B00010,B00010,B00010,B00110,B00110,B00110,B11011,
|
||||||
B00001,B00001,B00001,B00001,B00101,B00101,B00101,B11011
|
B00001,B00001,B00001,B00001,B00101,B00101,B00101,B11011
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
const PROGMEM uint8_t meters_bitmap[] = {
|
||||||
|
B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 , //custom 1
|
||||||
|
B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 , //custom 2
|
||||||
|
B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100 , //custom 3
|
||||||
|
B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110 , //custom 4
|
||||||
|
B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 , //custom 5
|
||||||
|
B01000, B11100, B01000, B00000, B10111, B10101, B10101, B10111 //custom 6
|
||||||
|
};
|
||||||
|
|
||||||
|
PGM_P p_metes_bitmap = reinterpret_cast<PGM_P>(meters_bitmap);
|
||||||
|
|
||||||
|
const PROGMEM uint8_t lock_bitmap[8] = {
|
||||||
|
0b01110,
|
||||||
|
0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b11111,
|
||||||
|
0b11011,
|
||||||
|
0b11011,
|
||||||
|
0b11111,
|
||||||
|
0b00000};
|
||||||
|
PGM_P plock_bitmap = reinterpret_cast<PGM_P>(lock_bitmap);
|
||||||
|
|
||||||
|
|
||||||
// initializes the custom characters
|
// initializes the custom characters
|
||||||
// we start from char 1 as char 0 terminates the string!
|
// we start from char 1 as char 0 terminates the string!
|
||||||
void initMeter(){
|
void initMeter(){
|
||||||
lcd.createChar(1, s_meter_bitmap);
|
uint8_t tmpbytes[8];
|
||||||
lcd.createChar(2, s_meter_bitmap + 8);
|
byte i;
|
||||||
lcd.createChar(3, s_meter_bitmap + 16);
|
|
||||||
lcd.createChar(4, s_meter_bitmap + 24);
|
for (i = 0; i < 8; i++)
|
||||||
lcd.createChar(5, s_meter_bitmap + 32);
|
tmpbytes[i] = pgm_read_byte(plock_bitmap + i);
|
||||||
lcd.createChar(6, s_meter_bitmap + 40);
|
lcd.createChar(0, tmpbytes);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i);
|
||||||
|
lcd.createChar(1, tmpbytes);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8);
|
||||||
|
lcd.createChar(2, tmpbytes);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16);
|
||||||
|
lcd.createChar(3, tmpbytes);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24);
|
||||||
|
lcd.createChar(4, tmpbytes);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32);
|
||||||
|
lcd.createChar(5, tmpbytes);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40);
|
||||||
|
lcd.createChar(6, tmpbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
//by KD8CEC
|
||||||
* The meter is drawn with special characters.
|
//0 ~ 25 : 30 over : + 10
|
||||||
* character 1 is used to simple draw the blocks of the scale of the meter
|
void drawMeter(int needle) {
|
||||||
* characters 2 to 6 are used to draw the needle in positions 1 to within the block
|
//5Char + O over
|
||||||
* This displays a meter from 0 to 100, -1 displays nothing
|
int drawCharLength = needle / 5;
|
||||||
*/
|
int drawCharLengthLast = needle % 5;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
if (needle >= 5)
|
||||||
|
lcdMeter[i] = 5; //full
|
||||||
|
else if (needle > 0)
|
||||||
|
lcdMeter[i] = needle; //full
|
||||||
|
else //0
|
||||||
|
lcdMeter[i] = 0x20;
|
||||||
|
|
||||||
|
needle -= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needle > 0)
|
||||||
|
lcdMeter[5] = 6;
|
||||||
|
else
|
||||||
|
lcdMeter[5] = 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void drawMeter(int8_t needle){
|
void drawMeter(int8_t needle){
|
||||||
int16_t best, i, s;
|
int16_t best, i, s;
|
||||||
|
|
||||||
@@ -62,20 +130,23 @@ void drawMeter(int8_t needle){
|
|||||||
s = (needle * 4)/10;
|
s = (needle * 4)/10;
|
||||||
for (i = 0; i < 8; i++){
|
for (i = 0; i < 8; i++){
|
||||||
if (s >= 5)
|
if (s >= 5)
|
||||||
meter[i] = 1;
|
lcdMeter[i] = 1;
|
||||||
else if (s >= 0)
|
else if (s >= 0)
|
||||||
meter[i] = 2 + s;
|
lcdMeter[i] = 2 + s;
|
||||||
else
|
else
|
||||||
meter[i] = 1;
|
lcdMeter[i] = 1;
|
||||||
s = s - 5;
|
s = s - 5;
|
||||||
}
|
}
|
||||||
if (needle >= 40)
|
if (needle >= 40)
|
||||||
meter[i-1] = 6;
|
lcdMeter[i-1] = 6;
|
||||||
meter[i] = 0;
|
lcdMeter[i] = 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// The generic routine to display one line on the LCD
|
// The generic routine to display one line on the LCD
|
||||||
void printLine(char linenmbr, char *c) {
|
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
|
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.setCursor(0, linenmbr); // place the cursor at the beginning of the selected line
|
||||||
lcd.print(c);
|
lcd.print(c);
|
||||||
@@ -87,39 +158,125 @@ void printLine(char linenmbr, char *c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// short cut to print to the first line
|
||||||
void printLine1(char *c){
|
void printLine1(const char *c){
|
||||||
printLine(1,c);
|
printLine(1,c);
|
||||||
}
|
}
|
||||||
// short cut to print to the first line
|
// short cut to print to the first line
|
||||||
void printLine2(char *c){
|
void printLine2(const char *c){
|
||||||
printLine(0,c);
|
printLine(0,c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clearLine2()
|
||||||
|
{
|
||||||
|
printLine2("");
|
||||||
|
line2DisplayStatus = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// short cut to print to the first line
|
||||||
|
void printLine1Clear(){
|
||||||
|
printLine(1,"");
|
||||||
|
}
|
||||||
|
// short cut to print to the first line
|
||||||
|
void printLine2Clear(){
|
||||||
|
printLine(0, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printLine2ClearAndUpdate(){
|
||||||
|
printLine(0, "");
|
||||||
|
line2DisplayStatus = 0;
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
//012...89ABC...Z
|
||||||
|
char byteToChar(byte srcByte){
|
||||||
|
if (srcByte < 10)
|
||||||
|
return 0x30 + srcByte;
|
||||||
|
else
|
||||||
|
return 'A' + srcByte - 10;
|
||||||
|
}
|
||||||
|
|
||||||
// this builds up the top line of the display with frequency and mode
|
// this builds up the top line of the display with frequency and mode
|
||||||
void updateDisplay() {
|
void updateDisplay() {
|
||||||
// tks Jack Purdum W8TEE
|
// tks Jack Purdum W8TEE
|
||||||
// replaced fsprint commmands by str commands for code size reduction
|
// 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));
|
memset(c, 0, sizeof(c));
|
||||||
memset(b, 0, sizeof(b));
|
|
||||||
|
|
||||||
ultoa(frequency, b, DEC);
|
|
||||||
|
|
||||||
if (inTx){
|
if (inTx){
|
||||||
if (cwTimeout > 0)
|
if (isCWAutoMode == 2) {
|
||||||
strcpy(c, " CW:");
|
for (i = 0; i < 4; i++)
|
||||||
else
|
c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' ');
|
||||||
strcpy(c, " TX:");
|
|
||||||
|
//display Sending Index
|
||||||
|
c[4] = byteToChar(sendingCWTextIndex);
|
||||||
|
c[5] = '=';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (cwTimeout > 0)
|
||||||
|
strcpy(c, " CW:");
|
||||||
|
else
|
||||||
|
strcpy(c, " TX:");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (ritOn)
|
if (ritOn)
|
||||||
strcpy(c, "RIT ");
|
strcpy(c, "RIT ");
|
||||||
else {
|
else {
|
||||||
if (isUSB)
|
if (cwMode == 0)
|
||||||
strcpy(c, "USB ");
|
{
|
||||||
|
if (isUSB)
|
||||||
|
strcpy(c, "USB ");
|
||||||
|
else
|
||||||
|
strcpy(c, "LSB ");
|
||||||
|
}
|
||||||
|
else if (cwMode == 1)
|
||||||
|
{
|
||||||
|
strcpy(c, "CWL ");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
strcpy(c, "LSB ");
|
{
|
||||||
|
strcpy(c, "CWU ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (vfoActive == VFO_A) // VFO A is active
|
if (vfoActive == VFO_A) // VFO A is active
|
||||||
strcat(c, "A:");
|
strcat(c, "A:");
|
||||||
@@ -127,29 +284,44 @@ void updateDisplay() {
|
|||||||
strcat(c, "B:");
|
strcat(c, "B:");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//display frequency
|
||||||
|
for (int i = 15; i >= 6; i--) {
|
||||||
//one mhz digit if less than 10 M, two digits if more
|
if (tmpFreq > 0) {
|
||||||
if (frequency < 10000000l){
|
if (i == 12 || i == 8) c[i] = '.';
|
||||||
c[6] = ' ';
|
else {
|
||||||
c[7] = b[0];
|
c[i] = tmpFreq % 10 + 0x30;
|
||||||
strcat(c, ".");
|
tmpFreq /= 10;
|
||||||
strncat(c, &b[1], 3);
|
}
|
||||||
strcat(c, ".");
|
}
|
||||||
strncat(c, &b[4], 3);
|
else
|
||||||
}
|
c[i] = ' ';
|
||||||
else {
|
|
||||||
strncat(c, b, 2);
|
|
||||||
strcat(c, ".");
|
|
||||||
strncat(c, &b[2], 3);
|
|
||||||
strcat(c, ".");
|
|
||||||
strncat(c, &b[5], 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inTx)
|
//remarked by KD8CEC
|
||||||
strcat(c, " TX");
|
//already RX/TX status display, and over index (16 x 2 LCD)
|
||||||
|
//if (inTx)
|
||||||
|
// strcat(c, " TX");
|
||||||
printLine(1, c);
|
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(":");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
//now, the second line
|
//now, the second line
|
||||||
memset(c, 0, sizeof(c));
|
memset(c, 0, sizeof(c));
|
||||||
@@ -196,9 +368,9 @@ int enc_read(void) {
|
|||||||
byte newState;
|
byte newState;
|
||||||
int enc_speed = 0;
|
int enc_speed = 0;
|
||||||
|
|
||||||
long stop_by = millis() + 50;
|
unsigned long start_at = millis();
|
||||||
|
|
||||||
while (millis() < stop_by) { // check if the previous state was stable
|
while (millis() - start_at < 50) { // check if the previous state was stable
|
||||||
newState = enc_state(); // Get current state
|
newState = enc_state(); // Get current state
|
||||||
|
|
||||||
if (newState != enc_prev_state)
|
if (newState != enc_prev_state)
|
||||||
|
Reference in New Issue
Block a user