Compare commits
112 Commits
cwtone-cfg
...
v1.061
Author | SHA1 | Date | |
---|---|---|---|
|
9c4b694ce2 | ||
|
5afcdf2583 | ||
|
075f585a1e | ||
|
d0c04df9d8 | ||
|
dd6d4555a8 | ||
|
8f8850f4da | ||
|
4e9437a735 | ||
|
bad62ef728 | ||
|
384c3c41b2 | ||
|
93727e6b22 | ||
|
31a7f79569 | ||
|
d7858e35c3 | ||
|
ecd104b686 | ||
|
bd52de59d2 | ||
|
f0409d641d | ||
|
8326b1ade3 | ||
|
94a3e5ca1b | ||
|
a26978f573 | ||
|
a21dbe2fa5 | ||
|
9faa8bb44c | ||
|
d926b15e3d | ||
|
fb2c9d2cc3 | ||
|
bf68dd6c26 | ||
|
4a6909f361 | ||
|
c911d26163 | ||
|
98e3b41f5a | ||
|
e0f9148972 | ||
|
277666f82f | ||
|
e532dccce7 | ||
|
81333e7af4 | ||
|
04949cdb93 | ||
|
bbdd0947d3 | ||
|
ed767f2e34 | ||
|
a374297d49 | ||
|
1e9576ddc2 | ||
|
a7684284d2 | ||
|
c1d81d9d5b | ||
|
3b4aaa664c | ||
|
d69588d999 | ||
|
14888bb7d7 | ||
|
57cd385b8a | ||
|
e915c21412 | ||
|
60777178a8 | ||
|
dd68b38454 | ||
|
d229a10092 | ||
|
3d019cdd44 | ||
|
55cfeeb924 | ||
|
c8879e0e59 | ||
|
4f5ac283b7 | ||
|
4745790dfa | ||
|
85832de034 | ||
|
4830db78cb | ||
|
5eca64d2a9 | ||
|
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 |
190
README.md
190
README.md
@@ -1,4 +1,194 @@
|
|||||||
|
#IMPORTANT INFORMATION
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
- Now Release Version 1.061 on my blog (http://www.hamskey.com)
|
||||||
|
- You can download and compiled hex file and uBITX Manager application on my blog (http://www.hamskey.com)
|
||||||
|
|
||||||
|
#NOTICE
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
I received uBITX a month ago and found that many features are required, and began coding with the idea of implementing minimal functionality as a general hf transceiver rather than an experimental device.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
- Reduce Program size
|
||||||
|
- uBITX with RTL-SDR
|
||||||
|
- Direct control for Student
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
## REVISION RECORD
|
||||||
|
1.07 (Working...)
|
||||||
|
- Please do not download it yet. The code will continue to change for the time being.
|
||||||
|
- BetaVersion for Reduce program size
|
||||||
|
|
||||||
|
1.061
|
||||||
|
- Added WSPR
|
||||||
|
You only need uBITX to use WSPR. No external devices are required.
|
||||||
|
Added Si5351 module for WSPR
|
||||||
|
- Update uBITX Manager to Version 1.0
|
||||||
|
- Reduce program size
|
||||||
|
for WSPR
|
||||||
|
for other Module
|
||||||
|
- Fixed IF Shift Bug
|
||||||
|
Disable IF Shift on TX
|
||||||
|
IF shift available in USB mode
|
||||||
|
Fixed cat routine in IF Shift setup
|
||||||
|
- Bugs fixed
|
||||||
|
cw start delay option
|
||||||
|
Auto key Bug
|
||||||
|
(found bug : LZ1LDO)
|
||||||
|
Message selection when Auto Key is used in RIT mode
|
||||||
|
(found bug : gerald)
|
||||||
|
- Improve CW Keying (start TX)
|
||||||
|
|
||||||
|
1.05
|
||||||
|
- include 1.05W, 1.051, 1.051W
|
||||||
|
- for WSPR Beta Test Version
|
||||||
|
|
||||||
|
1.04
|
||||||
|
- Optimized from Version1.03
|
||||||
|
- Reduce program size (97% -> 95%)
|
||||||
|
|
||||||
|
1.03
|
||||||
|
- Change eBFO Calibration Step (50 to 5)
|
||||||
|
- Change CW Frequency Display type
|
||||||
|
|
||||||
|
1.02
|
||||||
|
- Applied CW Start Delay to New CW Key logic (This is my mistake when applying the new CW Key Logic.Since uBITX operations are not significantly affected, this does not create a separate Release, It will be reflected in the next release.) - complete
|
||||||
|
- Modified CW Key Logic for Auto Key, (available AutoKey function by any cw keytype) - complete
|
||||||
|
- reduce cpu use usage (working)
|
||||||
|
- reduce (working)
|
||||||
|
|
||||||
|
1.01
|
||||||
|
- Fixed Cat problem with (IAMBIC A or B Selected)
|
||||||
|
1.0
|
||||||
|
- rename 0.30 to 1.0
|
||||||
|
|
||||||
|
0.35
|
||||||
|
- vfo to channel bug fixed (not saved mode -> fixed, channel has frequency and mode)
|
||||||
|
- add Channel tag (ch.1 ~ 10) by uBITX Manager
|
||||||
|
- add VFO to Channel, Channel To VFO
|
||||||
|
|
||||||
|
0.34
|
||||||
|
- TX Status check in auto Keysend logic
|
||||||
|
- optimize codes
|
||||||
|
- change default tune step size, and fixed bug
|
||||||
|
- change IF shift step (1Hz -> 50Hz)
|
||||||
|
|
||||||
|
0.33
|
||||||
|
- Added CWL, CWU Mode, (dont complete test yet)
|
||||||
|
- fixed VFO changed bug.
|
||||||
|
- Added Additional BFO for CWL, CWL
|
||||||
|
- Added IF Shift
|
||||||
|
- Change confirmation key PTT -> function key (not critical menus)
|
||||||
|
- Change CW Key Select type, (toggle -> select by dial)
|
||||||
|
|
||||||
|
0.32
|
||||||
|
- Added function Scroll Frequencty on upper line
|
||||||
|
- Added Example code for Draw meter and remarked (you can see and use this code in source codes)
|
||||||
|
- Added Split function, just toggle VFOs when TX/RX
|
||||||
|
|
||||||
|
0.31
|
||||||
|
- Fixed CW ADC Range error
|
||||||
|
- Display Message on Upper Line (anothor VFO Frequency, Tune Step, Selected Key Type)
|
||||||
|
|
||||||
|
0.30
|
||||||
|
- implemented the function to monitor the value of all analog inputs. This allows you to monitor the status of the CW keys connected to your uBITX.
|
||||||
|
- possible to set the ADC range for CW Keying. If no setting is made, it will have the same range as the original code. If you set the CW Keying ADC Values using uBITX Manager 0.3, you can reduce the key error.
|
||||||
|
- Added the function to select Straight Key, IAMBICA, IAMBICB key from the menu.
|
||||||
|
- default Band select is Ham Band mode, if you want common type, long press function key at band select menu, uBITX Manager can be used to modify frequencies to suit your country.
|
||||||
|
|
||||||
|
0.29
|
||||||
|
- Remove the use of initialization values in BFO settings - using crruent value, if factory reset
|
||||||
|
- Select Tune Step, default 0, 20, 50, 100, 200, Use the uBITX Manager to set the steps value you want. You can select Step by pressing and holding the Function Key (1sec ~ 2sec).
|
||||||
|
- Modify Dial Lock Function, Press the Function key for more than 3 seconds to toggle dial lock.
|
||||||
|
- created a new frequency tune method. remove original source codes, Threshold has been applied to reduce malfunction. checked the continuity of the user operating to make natural tune possible.
|
||||||
|
- stabilize and remove many warning messages - by Pullrequest and merge
|
||||||
|
- Changed cw keying method. removed the original code and applied Ron's code and Improved compatibility with original hardware and CAT commnication. It can be used without modification of hardware.
|
||||||
|
|
||||||
|
0.28
|
||||||
|
- Fixed CAT problem with hamlib on Linux
|
||||||
|
- restore Protocol autorecovery logic
|
||||||
|
|
||||||
|
0.27
|
||||||
|
(First alpha test version, This will be renamed to the major version 1.0)
|
||||||
|
- Dual VFO Dial Lock (vfoA Dial lock)
|
||||||
|
- 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
|
||||||
|
795
ubitx_20/cat_libs.ino
Normal file
795
ubitx_20/cat_libs.ino
Normal file
@@ -0,0 +1,795 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
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)
|
||||||
|
void CatGetFreqMode(unsigned long freq) //for remove warning messages
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
void CatSetSplit(boolean isSplit) //for remove warning messages
|
||||||
|
{
|
||||||
|
if (isSplit)
|
||||||
|
splitOn = 1;
|
||||||
|
else
|
||||||
|
splitOn = 0;
|
||||||
|
|
||||||
|
Serial.write(ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CatSetPTT(boolean isPTTOn, byte fromType)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
if ((!inTx) && (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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
void ReadEEPRom() //for remove warnings.
|
||||||
|
{
|
||||||
|
//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)
|
||||||
|
void WriteEEPRom(void) //for remove warning
|
||||||
|
{
|
||||||
|
//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)
|
||||||
|
void ReadEEPRom_FT817(void) //for remove warnings
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
void CatRxStatus(void) //for remove warning
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
void CatTxStatus(void) //for remove warning
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x03 : //Read Frequency and mode
|
||||||
|
CatGetFreqMode(frequency);
|
||||||
|
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(); //Call by uBITX Manager Program
|
||||||
|
break;
|
||||||
|
case 0xBB: //Read FT-817 EEPROM Data (for comfirtable)
|
||||||
|
ReadEEPRom_FT817();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xDC: //Write uBITX EEPROM Data
|
||||||
|
WriteEEPRom(); //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();
|
||||||
|
break;
|
||||||
|
case 0xF7: //Read TX Status
|
||||||
|
CatTxStatus();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
422
ubitx_20/cw_autokey.ino
Normal file
422
ubitx_20/cw_autokey.ino
Normal file
@@ -0,0 +1,422 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
KD8CEC's Memory Keyer for HAM
|
||||||
|
|
||||||
|
This source code is written for All amateur radio operator,
|
||||||
|
I have not had amateur radio communication for a long time. CW has been
|
||||||
|
around for a long time, and I do not know what kind of keyer and keying
|
||||||
|
software is fashionable. So I implemented the functions I need mainly.
|
||||||
|
|
||||||
|
To minimize the use of memory space, we used bitwise operations.
|
||||||
|
For the alphabet, I put Morsecode in 1 byte. The front 4Bit is the length
|
||||||
|
and the 4Bit is the Morse code. Because the number is fixed in length,
|
||||||
|
there is no separate length information. The 5Bit on the right side is
|
||||||
|
the Morse code.
|
||||||
|
|
||||||
|
I wrote this code myself, so there is no license restriction.
|
||||||
|
So this code allows anyone to write with confidence.
|
||||||
|
But keep it as long as the original author of the code.
|
||||||
|
DE Ian KD8CEC
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
**************************************************************************/
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
//27 + 10 + 18 + 1(SPACE) = //56
|
||||||
|
const PROGMEM uint8_t cwAZTable[27] = {0b00100100 , 0b01001000 , 0b01001010 , 0b00111000 , 0b00010000, 0b01000010, 0b00111100, 0b01000000 , //A ~ H
|
||||||
|
0b00100000, 0b01000111 ,0b00111010, 0b01000100, 0b00101100, 0b00101000 , 0b00111110, 0b01000110, 0b01001101, 0b00110100, //I ~ R
|
||||||
|
0b00110000, 0b00011000, 0b00110010, 0b01000001, 0b00110110, 0b01001001, 0b01001011, 0b01001100}; //S ~ Z
|
||||||
|
PGM_P pCwAZTable = reinterpret_cast<PGM_P>(cwAZTable);
|
||||||
|
|
||||||
|
const PROGMEM uint8_t cw09Table[27] = {0b00011111, 0b00001111, 0b00000111, 0b00000011, 0b00000001, 0b00000000, 0b00010000, 0b00011000, 0b00011100, 0b00011110};
|
||||||
|
PGM_P pcw09Table = reinterpret_cast<PGM_P>(cw09Table);
|
||||||
|
|
||||||
|
//# : AR, ~:BT, [:AS, ]:SK, ^:KN
|
||||||
|
const PROGMEM uint8_t cwSymbolIndex[] = {'.', ',', '?', '"', '!', '/', '(', ')', '&', ':', ';', '=', '+', '-', '_', '\'', '@', '#', '~', '[', ']', '^' };
|
||||||
|
PGM_P pCwSymbolIndex = reinterpret_cast<PGM_P>(cwSymbolIndex);
|
||||||
|
|
||||||
|
const PROGMEM uint8_t cwSymbolTable[] = {0b11010101, 0b11110011, 0b11001100, 0b11011110, 0b11101011, 0b10100100, 0b10101100, 0b11101101, 0b10010000, 0b11111000, 0b11101010, 0b10100010, 0b10010100, 0b11100001, 0b11001101, 0b11010010, 0b11011010, 0b10010100, 0b10100010, 0b10010000, 0b11000101, 0b10101100};
|
||||||
|
PGM_P pCwSymbolTable = reinterpret_cast<PGM_P>(cwSymbolTable);
|
||||||
|
////const PROGMEM uint8_t cwSymbolLength[] = {6, 6, 6, 6, 6, 5, 5, 6, 5, 6, 6, 5, 5, 6, 6, 6, 6, 5, 5, 5, 6, 5};
|
||||||
|
|
||||||
|
// ":(Start"), ':(End "), >: My callsign, <:QSO Callsign (Second Callsign), #:AR, ~:BT, [:AS, ]:SK
|
||||||
|
|
||||||
|
byte knobPosition = 0;
|
||||||
|
//byte cwTextData[30]; //Maximum 30 Remarked by KD8CE -> Direct Read EEPROM
|
||||||
|
byte autoCWSendCharEndIndex = 0;
|
||||||
|
byte autoCWSendCharIndex = 0;
|
||||||
|
unsigned long autoCWbeforeTime = 0; //for interval time between chars
|
||||||
|
byte pttBeforeStatus = 1; //PTT : default high
|
||||||
|
byte isKeyStatusAfterCWStart = 0; //0 : Init, 1 : Keyup after auto CW Start, 2 : Keydown after
|
||||||
|
byte selectedCWTextIndex = 0;
|
||||||
|
unsigned long autoCWKeydownCheckTime = 0; //for interval time between chars
|
||||||
|
byte changeReserveStatus = 0;
|
||||||
|
byte isAutoCWHold = 0; //auto CW Pause => Manual Keying => auto
|
||||||
|
|
||||||
|
void autoSendPTTCheck()
|
||||||
|
{
|
||||||
|
if (isCWAutoMode == 2) { //Sending Mode
|
||||||
|
//check PTT Button
|
||||||
|
//short Press => reservation or cancel
|
||||||
|
//long Press => Hold
|
||||||
|
if (digitalRead(PTT) == LOW)
|
||||||
|
{
|
||||||
|
//if (isKeyStatusAfterCWStart == 0) //Yet Press PTT from start TX
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (isKeyStatusAfterCWStart == 1) //while auto cw send, ptt up and ptt down again
|
||||||
|
{
|
||||||
|
//Start Time
|
||||||
|
autoCWKeydownCheckTime = millis() + 200; //Long push time
|
||||||
|
isKeyStatusAfterCWStart = 2; //Change status => ptt down agian
|
||||||
|
}
|
||||||
|
else if (isKeyStatusAfterCWStart == 2 && autoCWKeydownCheckTime < millis())
|
||||||
|
{
|
||||||
|
//Hold Mode
|
||||||
|
isAutoCWHold = 1;
|
||||||
|
isKeyStatusAfterCWStart = 3;
|
||||||
|
}
|
||||||
|
else if (isKeyStatusAfterCWStart == 3)
|
||||||
|
{
|
||||||
|
autoCWKeydownCheckTime = millis() + 200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//PTT UP
|
||||||
|
if (isKeyStatusAfterCWStart == 2) //0 (down before cw start) -> 1 (up while cw sending) -> 2 (down while cw sending)
|
||||||
|
{
|
||||||
|
if (autoCWKeydownCheckTime > millis()) //Short : Reservation or cancel Next Text
|
||||||
|
{
|
||||||
|
if (autoCWSendReservCount == 0 ||
|
||||||
|
(autoCWSendReservCount < AUTO_CW_RESERVE_MAX &&
|
||||||
|
autoCWSendReserv[autoCWSendReservCount - 1] != selectedCWTextIndex))
|
||||||
|
{
|
||||||
|
//Reserve
|
||||||
|
autoCWSendReserv[autoCWSendReservCount++] = selectedCWTextIndex;
|
||||||
|
changeReserveStatus = 1;
|
||||||
|
}
|
||||||
|
else if (autoCWSendReservCount > 0 && autoCWSendReserv[autoCWSendReservCount - 1] == selectedCWTextIndex)
|
||||||
|
{
|
||||||
|
autoCWSendReservCount--;
|
||||||
|
changeReserveStatus = 1;
|
||||||
|
}
|
||||||
|
} // end of Short Key up
|
||||||
|
}
|
||||||
|
else if (isKeyStatusAfterCWStart == 3) //play from Hold (pause Auto CW Send)
|
||||||
|
{
|
||||||
|
isAutoCWHold = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
isKeyStatusAfterCWStart = 1; //Change status => ptt up (while cw send mode)
|
||||||
|
} //end of PTT UP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send 1 char
|
||||||
|
void sendCWChar(char cwKeyChar)
|
||||||
|
{
|
||||||
|
byte sendBuff[7];
|
||||||
|
byte i, j, charLength;
|
||||||
|
byte tmpChar;
|
||||||
|
|
||||||
|
//For Macrofunction
|
||||||
|
//replace > and < to My callsign, qso callsign, use recursive function call
|
||||||
|
if (cwKeyChar == '>' || cwKeyChar == '<')
|
||||||
|
{
|
||||||
|
uint16_t callsignStartIndex = 0;
|
||||||
|
uint16_t callsignEndIndex = 0;
|
||||||
|
|
||||||
|
if (cwKeyChar == '>') //replace my callsign
|
||||||
|
{
|
||||||
|
if (userCallsignLength > 0)
|
||||||
|
{
|
||||||
|
callsignStartIndex = 0;
|
||||||
|
callsignEndIndex = userCallsignLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cwKeyChar == '<') //replace qso callsign
|
||||||
|
{
|
||||||
|
//ReadLength
|
||||||
|
callsignEndIndex = EEPROM.read(CW_STATION_LEN);
|
||||||
|
if (callsignEndIndex > 0)
|
||||||
|
{
|
||||||
|
callsignStartIndex = CW_STATION_LEN - callsignEndIndex - USER_CALLSIGN_DAT;
|
||||||
|
callsignEndIndex = callsignStartIndex + callsignEndIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callsignStartIndex == 0 && callsignEndIndex == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (uint16_t i = callsignStartIndex; i <= callsignEndIndex; i++)
|
||||||
|
{
|
||||||
|
sendCWChar(EEPROM.read(USER_CALLSIGN_DAT + i));
|
||||||
|
autoSendPTTCheck(); //for reserve and cancel next CW Text
|
||||||
|
if (changeReserveStatus == 1)
|
||||||
|
{
|
||||||
|
changeReserveStatus = 0;
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < callsignEndIndex) delay_background(cwSpeed * 3, 4); //
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (cwKeyChar >= 'A' && cwKeyChar <= 'Z') //Encode Char by KD8CEC
|
||||||
|
{
|
||||||
|
tmpChar = pgm_read_byte(pCwAZTable + (cwKeyChar - 'A'));
|
||||||
|
charLength = (tmpChar >> 4) & 0x0F;
|
||||||
|
for (i = 0; i < charLength; i++)
|
||||||
|
sendBuff[i] = (tmpChar << i) & 0x08;
|
||||||
|
}
|
||||||
|
else if (cwKeyChar >= '0' && cwKeyChar <= '9')
|
||||||
|
{
|
||||||
|
charLength = 5;
|
||||||
|
for (i = 0; i < charLength; i++)
|
||||||
|
sendBuff[i] = (pgm_read_byte(pcw09Table + (cwKeyChar - '0')) << i) & 0x10;
|
||||||
|
}
|
||||||
|
else if (cwKeyChar == ' ')
|
||||||
|
{
|
||||||
|
charLength = 0;
|
||||||
|
delay_background(cwSpeed * 4, 4); //7 -> basic interval is 3
|
||||||
|
}
|
||||||
|
else if (cwKeyChar == '$') //7 digit
|
||||||
|
{
|
||||||
|
charLength = 7;
|
||||||
|
for (i = 0; i < 7; i++)
|
||||||
|
sendBuff[i] = (0b00010010 << i) & 0x80; //...1..1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//symbol
|
||||||
|
for (i = 0; i < 22; i++)
|
||||||
|
{
|
||||||
|
if (pgm_read_byte(pCwSymbolIndex + i) == cwKeyChar)
|
||||||
|
{
|
||||||
|
tmpChar = pgm_read_byte(pCwSymbolTable + i);
|
||||||
|
charLength = ((tmpChar >> 6) & 0x03) + 3;
|
||||||
|
|
||||||
|
for (j = 0; j < charLength; j++)
|
||||||
|
sendBuff[j] = (tmpChar << (j + 2)) & 0x80;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
charLength = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < charLength; i++)
|
||||||
|
{
|
||||||
|
cwKeydown();
|
||||||
|
if (sendBuff[i] == 0)
|
||||||
|
delay_background(cwSpeed, 4);
|
||||||
|
else
|
||||||
|
delay_background(cwSpeed * 3, 4);
|
||||||
|
cwKeyUp();
|
||||||
|
if (i != charLength -1)
|
||||||
|
delay_background(cwSpeed, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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, 0);
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
if (!inTx){ //if not TX Status, change RX -> TX
|
||||||
|
keyDown = 0;
|
||||||
|
startTx(TX_CW, 0); //disable updateDisplay Command for reduce latency time
|
||||||
|
}
|
||||||
|
|
||||||
|
sendCWChar(EEPROM.read(CW_AUTO_DATA + autoCWSendCharIndex++));
|
||||||
|
|
||||||
|
if (autoCWSendCharIndex > autoCWSendCharEndIndex) { //finish auto cw send
|
||||||
|
//check reserve status
|
||||||
|
if (autoCWSendReservCount > 0)
|
||||||
|
{
|
||||||
|
//prepare
|
||||||
|
sendingCWTextIndex = autoCWSendReserv[0];
|
||||||
|
|
||||||
|
for (i = 0; i < AUTO_CW_RESERVE_MAX -1; i++)
|
||||||
|
autoCWSendReserv[i] = autoCWSendReserv[i + 1];
|
||||||
|
|
||||||
|
EEPROM.get(CW_AUTO_DATA + (sendingCWTextIndex * 2), cwStartIndex);
|
||||||
|
EEPROM.get(CW_AUTO_DATA + (sendingCWTextIndex * 2 + 1), cwEndIndex);
|
||||||
|
|
||||||
|
//Information about Auto Send CW Text
|
||||||
|
autoCWSendCharEndIndex = cwEndIndex; //length of CW Text //ianlee
|
||||||
|
autoCWSendCharIndex = cwStartIndex; //position of Sending Char //ianlee
|
||||||
|
autoCWSendReservCount--; //Decrease
|
||||||
|
|
||||||
|
sendCWChar(' '); //APPLY SPACE between CW Texts
|
||||||
|
changeReserveStatus = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isCWAutoMode = 1; //ready status
|
||||||
|
delay_background(cwDelayTime * 10, 2);
|
||||||
|
stopTx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
autoCWbeforeTime = millis();
|
||||||
|
|
||||||
|
if (changeReserveStatus == 1)
|
||||||
|
{
|
||||||
|
changeReserveStatus = 0;
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//abort if this button is down
|
||||||
|
if (btnDown())
|
||||||
|
{
|
||||||
|
isCWAutoMode = 0; //dsiable Auto CW Mode
|
||||||
|
printLine2ClearAndUpdate();
|
||||||
|
delay_background(1000, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
80
ubitx_20/ubitx.h
Normal file
80
ubitx_20/ubitx.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
header file for C++ by KD8CEC
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
**************************************************************************/
|
||||||
|
#define WSPR_COUNT 443 //WSPR_MESSAGE_COUNT
|
||||||
|
#define WSPR_MESSAGE1 444 //
|
||||||
|
#define WSPR_MESSAGE2 490 //
|
||||||
|
#define WSPR_MESSAGE3 536 //
|
||||||
|
#define WSPR_MESSAGE4 582 //
|
||||||
|
|
||||||
|
#define WSPR_BAND_COUNT 3
|
||||||
|
|
||||||
|
#define TX_SSB 0
|
||||||
|
#define TX_CW 1
|
||||||
|
|
||||||
|
|
||||||
|
extern void printLine1(const char *c);
|
||||||
|
extern void printLine2(const char *c);
|
||||||
|
extern void printLineF(char linenmbr, const __FlashStringHelper *c);
|
||||||
|
extern void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetType);
|
||||||
|
extern byte delay_background(unsigned delayTime, byte fromType);
|
||||||
|
extern int btnDown(void);
|
||||||
|
extern char c[30];
|
||||||
|
extern char b[30];
|
||||||
|
|
||||||
|
extern unsigned long frequency;
|
||||||
|
|
||||||
|
#define printLineF1(x) (printLineF(1, x))
|
||||||
|
#define printLineF2(x) (printLineF(0, x))
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig.
|
||||||
|
* This assignment is as follows :
|
||||||
|
* Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
||||||
|
* GND +5V CLK0 GND GND CLK1 GND GND CLK2 GND D2 D3 D4 D5 D6 D7
|
||||||
|
* These too are flexible with what you may do with them, for the Raduino, we use them to :
|
||||||
|
* - TX_RX line : Switches between Transmit and Receive after sensing the PTT or the morse keyer
|
||||||
|
* - CW_KEY line : turns on the carrier for CW
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TX_RX (7)
|
||||||
|
#define CW_TONE (6)
|
||||||
|
#define TX_LPF_A (5)
|
||||||
|
#define TX_LPF_B (4)
|
||||||
|
#define TX_LPF_C (3)
|
||||||
|
#define CW_KEY (2)
|
||||||
|
|
||||||
|
//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes
|
||||||
|
//these are the parameter passed to startTx
|
||||||
|
#define TX_SSB 0
|
||||||
|
#define TX_CW 1
|
||||||
|
|
||||||
|
extern void si5351bx_init(void);
|
||||||
|
extern void si5351bx_setfreq(uint8_t clknum, uint32_t fout);
|
||||||
|
extern void si5351_set_calibration(int32_t cal);
|
||||||
|
extern void initOscillators(void);
|
||||||
|
extern void Set_WSPR_Param(void);
|
||||||
|
extern void TXSubFreq(unsigned long P2);
|
||||||
|
|
||||||
|
extern void startTx(byte txMode, byte isDisplayUpdate);
|
||||||
|
extern void stopTx(void);
|
||||||
|
extern void setTXFilters(unsigned long freq);
|
||||||
|
|
||||||
|
extern void SendWSPRManage(void);
|
||||||
|
extern byte WsprMSGCount;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||||
|
254
ubitx_20/ubitx_idle.ino
Normal file
254
ubitx_20/ubitx_idle.ino
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
KD8CEC's uBITX Idle time Processing
|
||||||
|
Functions that run at times that do not affect TX, CW, and CAT
|
||||||
|
It is called in 1/10 time unit.
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
**************************************************************************/
|
||||||
|
char line2Buffer[16];
|
||||||
|
//KD8CEC 200Hz ST
|
||||||
|
//L14.150 200Hz ST
|
||||||
|
//U14.150 +150khz
|
||||||
|
int freqScrollPosition = 0;
|
||||||
|
//Example Line2 Optinal Display
|
||||||
|
//immediate execution, not call by scheulder
|
||||||
|
void updateLine2Buffer(char isDirectCall)
|
||||||
|
{
|
||||||
|
unsigned long tmpFreq = 0;
|
||||||
|
if (isDirectCall == 0)
|
||||||
|
{
|
||||||
|
if (ritOn)
|
||||||
|
{
|
||||||
|
strcpy(line2Buffer, "RitTX:");
|
||||||
|
|
||||||
|
//display frequency
|
||||||
|
tmpFreq = ritTxFrequency;
|
||||||
|
for (int i = 15; i >= 6; i--) {
|
||||||
|
if (tmpFreq > 0) {
|
||||||
|
if (i == 12 || i == 8) line2Buffer[i] = '.';
|
||||||
|
else {
|
||||||
|
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||||
|
tmpFreq /= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
line2Buffer[i] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} //end of ritOn display
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
//other VFO display
|
||||||
|
//======================================================
|
||||||
|
if (vfoActive == VFO_B)
|
||||||
|
{
|
||||||
|
tmpFreq = vfoA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmpFreq = vfoB;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXAMPLE 1 & 2
|
||||||
|
//U14.150.100
|
||||||
|
//display frequency
|
||||||
|
for (int i = 9; i >= 0; i--) {
|
||||||
|
if (tmpFreq > 0) {
|
||||||
|
if (i == 2 || i == 6) line2Buffer[i] = '.';
|
||||||
|
else {
|
||||||
|
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||||
|
tmpFreq /= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
line2Buffer[i] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
//EXAMPLE #1
|
||||||
|
if ((displayOption1 & 0x04) == 0x00) //none scroll display
|
||||||
|
line2Buffer[6] = 'k';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//example #2
|
||||||
|
if (freqScrollPosition++ > 18) //none scroll display time
|
||||||
|
{
|
||||||
|
line2Buffer[6] = 'k';
|
||||||
|
if (freqScrollPosition > 25)
|
||||||
|
freqScrollPosition = -1;
|
||||||
|
}
|
||||||
|
else //scroll frequency
|
||||||
|
{
|
||||||
|
line2Buffer[10] = 'H';
|
||||||
|
line2Buffer[11] = 'z';
|
||||||
|
|
||||||
|
if (freqScrollPosition < 7)
|
||||||
|
{
|
||||||
|
for (int i = 11; i >= 0; i--)
|
||||||
|
if (i - (7 - freqScrollPosition) >= 0)
|
||||||
|
line2Buffer[i] = line2Buffer[i - (7 - freqScrollPosition)];
|
||||||
|
else
|
||||||
|
line2Buffer[i] = ' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 11; i++)
|
||||||
|
if (i + (freqScrollPosition - 7) <= 11)
|
||||||
|
line2Buffer[i] = line2Buffer[i + (freqScrollPosition - 7)];
|
||||||
|
else
|
||||||
|
line2Buffer[i] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} //scroll
|
||||||
|
|
||||||
|
line2Buffer[7] = ' ';
|
||||||
|
} //check direct call by encoder
|
||||||
|
|
||||||
|
if (isIFShift)
|
||||||
|
{
|
||||||
|
if (isDirectCall == 1)
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
line2Buffer[i] = ' ';
|
||||||
|
|
||||||
|
//IFShift Offset Value
|
||||||
|
line2Buffer[8] = 'I';
|
||||||
|
line2Buffer[9] = 'F';
|
||||||
|
|
||||||
|
//if (ifShiftValue == 0)
|
||||||
|
//{
|
||||||
|
/*
|
||||||
|
line2Buffer[10] = 'S';
|
||||||
|
line2Buffer[11] = ':';
|
||||||
|
line2Buffer[12] = 'O';
|
||||||
|
line2Buffer[13] = 'F';
|
||||||
|
line2Buffer[14] = 'F';
|
||||||
|
*/
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0;
|
||||||
|
line2Buffer[11] = 0;
|
||||||
|
line2Buffer[12] = ' ';
|
||||||
|
|
||||||
|
//11, 12, 13, 14, 15
|
||||||
|
memset(b, 0, sizeof(b));
|
||||||
|
ltoa(ifShiftValue, b, DEC);
|
||||||
|
strncat(line2Buffer, b, 5);
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (isDirectCall == 1) //if call by encoder (not scheduler), immediate print value
|
||||||
|
printLine2(line2Buffer);
|
||||||
|
} // end of display IF
|
||||||
|
else // step display
|
||||||
|
{
|
||||||
|
if (isDirectCall != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset(&line2Buffer[8], ' ', 8);
|
||||||
|
//Step
|
||||||
|
long tmpStep = arTuneStep[tuneStepIndex -1];
|
||||||
|
|
||||||
|
byte isStepKhz = 0;
|
||||||
|
if (tmpStep >= 1000)
|
||||||
|
{
|
||||||
|
isStepKhz = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 10; i >= 8 - isStepKhz; i--) {
|
||||||
|
if (tmpStep > 0) {
|
||||||
|
line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30;
|
||||||
|
tmpStep /= 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
line2Buffer[i +isStepKhz] = ' ';
|
||||||
|
}
|
||||||
|
//if (isStepKhz == 1)
|
||||||
|
// line2Buffer[10] = 'k';
|
||||||
|
|
||||||
|
if (isStepKhz == 0)
|
||||||
|
{
|
||||||
|
line2Buffer[11] = 'H';
|
||||||
|
line2Buffer[12] = 'z';
|
||||||
|
}
|
||||||
|
|
||||||
|
line2Buffer[13] = ' ';
|
||||||
|
//if (
|
||||||
|
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
||||||
|
if (cwKeyType == 0)
|
||||||
|
{
|
||||||
|
line2Buffer[14] = 'S';
|
||||||
|
line2Buffer[15] = 'T';
|
||||||
|
}
|
||||||
|
else if (cwKeyType == 1)
|
||||||
|
{
|
||||||
|
line2Buffer[14] = 'I';
|
||||||
|
line2Buffer[15] = 'A';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line2Buffer[14] = 'I';
|
||||||
|
line2Buffer[15] = 'B';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//meterType : 0 = S.Meter, 1 : P.Meter
|
||||||
|
void DisplayMeter(byte meterType, byte meterValue, char drawPosition)
|
||||||
|
{
|
||||||
|
if (meterType == 0 || meterType == 1 || meterType == 2)
|
||||||
|
{
|
||||||
|
drawMeter(meterValue); //call original source code
|
||||||
|
int lineNumber = 0;
|
||||||
|
if ((displayOption1 & 0x01) == 0x01)
|
||||||
|
lineNumber = 1;
|
||||||
|
|
||||||
|
lcd.setCursor(drawPosition, lineNumber);
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6
|
||||||
|
lcd.write(lcdMeter[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte testValue = 0;
|
||||||
|
char checkCount = 0;
|
||||||
|
void idle_process()
|
||||||
|
{
|
||||||
|
//space for user graphic display
|
||||||
|
if (menuOn == 0)
|
||||||
|
{
|
||||||
|
if ((displayOption1 & 0x10) == 0x10) //always empty topline
|
||||||
|
return;
|
||||||
|
|
||||||
|
//if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message
|
||||||
|
if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) {
|
||||||
|
if (checkCount++ > 1)
|
||||||
|
{
|
||||||
|
updateLine2Buffer(0); //call by scheduler
|
||||||
|
printLine2(line2Buffer);
|
||||||
|
line2DisplayStatus = 2;
|
||||||
|
checkCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//EX for Meters
|
||||||
|
/*
|
||||||
|
DisplayMeter(0, testValue++, 7);
|
||||||
|
if (testValue > 30)
|
||||||
|
testValue = 0;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -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,207 @@ 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 unsigned long ktimer;
|
||||||
|
unsigned char keyerState = IDLE;
|
||||||
|
|
||||||
|
//Below is a test to reduce the keying error. do not delete lines
|
||||||
|
//create by KD8CEC for compatible with new CW Logic
|
||||||
|
char update_PaddleLatch(byte isUpdateKeyState) {
|
||||||
|
unsigned char tmpKeyerControl = 0;
|
||||||
|
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){
|
||||||
|
lastPaddle = 0;
|
||||||
|
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:
|
||||||
|
//modified KD8CEC
|
||||||
|
/*
|
||||||
|
ktimer += millis(); // set ktimer to interval end time
|
||||||
|
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
||||||
|
keyerState = KEYED; // next state
|
||||||
|
if (!inTx){
|
||||||
|
//DelayTime Option
|
||||||
|
delay_background(delayBeforeCWStartTime * 2, 2);
|
||||||
|
|
||||||
|
keyDown = 0;
|
||||||
|
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
||||||
|
startTx(TX_CW, 1);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (!inTx){
|
||||||
|
//DelayTime Option
|
||||||
|
delay_background(delayBeforeCWStartTime * 2, 2);
|
||||||
|
|
||||||
|
keyDown = 0;
|
||||||
|
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
||||||
|
startTx(TX_CW, 1);
|
||||||
|
}
|
||||||
|
ktimer += millis(); // set ktimer to interval end time
|
||||||
|
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
||||||
|
keyerState = KEYED; // next state
|
||||||
|
|
||||||
|
cwKeydown();
|
||||||
|
break;
|
||||||
|
|
||||||
|
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(2);
|
||||||
|
} //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){
|
||||||
|
//DelayTime Option
|
||||||
|
delay_background(delayBeforeCWStartTime * 2, 2);
|
||||||
|
|
||||||
|
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) //removed by KD8CEC
|
||||||
|
// return;
|
||||||
|
// got back to the beginning of the loop, if no further activity happens on straight key
|
||||||
|
// we will time out, and return out of this routine
|
||||||
|
//delay(5);
|
||||||
|
//delay_background(5, 3); //removed by KD8CEC
|
||||||
|
//continue; //removed by KD8CEC
|
||||||
|
return; //Tx stop control by Main Loop
|
||||||
|
}
|
||||||
|
|
||||||
|
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 +288,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 +301,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 +364,6 @@ void cwKeyer(){
|
|||||||
delay(cwSpeed);
|
delay(cwSpeed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,19 @@
|
|||||||
|
/************************************************************************************
|
||||||
|
* KD8CEC
|
||||||
|
* kd8cec@gmail.com http://www.hamskey.com
|
||||||
|
*
|
||||||
|
* Merge two SI5351 Librarys
|
||||||
|
* KE7ER's fixed vco and variable Clocks Configure values
|
||||||
|
* G3ZIL's fixed Clock Configure Value and variable VCO
|
||||||
|
* * I have combined the two libraries above. All licenses follow the above library.
|
||||||
|
*
|
||||||
|
* PLL-A is generated by fixing 850Mhz clock. All output clocks use PLL-A to
|
||||||
|
* generate the frequency. This is the method used in QRP radios such as uBITX.
|
||||||
|
* When switching to WSPR transmission mode, PLL-B operates for the base frequency to transmit WSPR.
|
||||||
|
* The output clock channel that controls the frequency is connected to the PLL-B.
|
||||||
|
* The WSPR protocol is generated by changing the clock of the PLL-B.
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
// ************* SI5315 routines - tks Jerry Gaffke, KE7ER ***********************
|
// ************* SI5315 routines - tks Jerry Gaffke, KE7ER ***********************
|
||||||
|
|
||||||
// An minimalist standalone set of Si5351 routines.
|
// An minimalist standalone set of Si5351 routines.
|
||||||
@@ -60,19 +76,22 @@ void i2cWriten(uint8_t reg, uint8_t *vals, uint8_t vcnt) { // write array
|
|||||||
Wire.endTransmission();
|
Wire.endTransmission();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t si5351Val[8] = {0, 1, 0, 0, 0, 0, 0, 0}; //for reduce program memory size
|
||||||
|
|
||||||
void si5351bx_init() { // Call once at power-up, start PLLA
|
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
|
||||||
i2cWrite(183, SI5351BX_XTALPF << 6); // Set 25mhz crystal load capacitance
|
i2cWrite(183, SI5351BX_XTALPF << 6); // Set 25mhz crystal load capacitance
|
||||||
msxp1 = 128 * SI5351BX_MSA - 512; // and msxp2=0, msxp3=1, not fractional
|
msxp1 = 128 * SI5351BX_MSA - 512; // and msxp2=0, msxp3=1, not fractional
|
||||||
uint8_t vals[8] = {0, 1, BB2(msxp1), BB1(msxp1), BB0(msxp1), 0, 0, 0};
|
//uint8_t vals[8] = {0, 1, BB2(msxp1), BB1(msxp1), BB0(msxp1), 0, 0, 0};
|
||||||
i2cWriten(26, vals, 8); // Write to 8 PLLA msynth regs
|
si5351Val[2] = BB2(msxp1);
|
||||||
|
si5351Val[3] = BB1(msxp1);
|
||||||
|
si5351Val[4] = BB0(msxp1);
|
||||||
|
|
||||||
|
i2cWriten(26, si5351Val, 8); // Write to 8 PLLA msynth regs
|
||||||
i2cWrite(177, 0x20); // Reset PLLA (0x80 resets PLLB)
|
i2cWrite(177, 0x20); // Reset PLLA (0x80 resets PLLB)
|
||||||
// for (reg=16; reg<=23; reg++) i2cWrite(reg, 0x80); // Powerdown CLK's
|
|
||||||
// i2cWrite(187, 0); // No fannout of clkin, xtal, ms0, ms4
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void si5351bx_setfreq(uint8_t clknum, uint32_t fout) { // Set a CLK to fout Hz
|
void si5351bx_setfreq(uint8_t clknum, uint32_t fout) { // Set a CLK to fout Hz
|
||||||
@@ -105,11 +124,48 @@ void si5351_set_calibration(int32_t cal){
|
|||||||
si5351bx_setfreq(0, usbCarrier);
|
si5351bx_setfreq(0, usbCarrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetCarrierFreq()
|
||||||
|
{
|
||||||
|
unsigned long appliedCarrier = ((cwMode == 0 ? usbCarrier : cwmCarrier) + (isIFShift && (inTx == 0) ? ifShiftValue : 0));
|
||||||
|
si5351bx_setfreq(0, appliedCarrier);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (cwMode == 0)
|
||||||
|
si5351bx_setfreq(0, usbCarrier + (isIFShift ? ifShiftValue : 0));
|
||||||
|
else
|
||||||
|
si5351bx_setfreq(0, cwmCarrier + (isIFShift ? ifShiftValue : 0));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
void initOscillators(){
|
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);
|
SetCarrierFreq();
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================
|
||||||
|
// ADD FUNCTIONS by KD8CEC
|
||||||
|
//============================================================
|
||||||
|
uint8_t Wspr_Reg1[8] = {0xFF,0xFE, 0x00, 0, 0, 0, 0, 0}; //3, 4, 5, 6, 7
|
||||||
|
uint8_t Wspr_Reg2[8] = {0, 1, 0, 0, 0, 0, 0, 0}; //2, 3, 4
|
||||||
|
|
||||||
|
void Set_WSPR_Param(void)
|
||||||
|
{
|
||||||
|
i2cWrite(18, 128);
|
||||||
|
i2cWriten(34, Wspr_Reg1, 8);
|
||||||
|
i2cWriten(58, Wspr_Reg2, 8);
|
||||||
|
i2cWrite(177, 128);
|
||||||
|
i2cWrite(18, 111);
|
||||||
|
|
||||||
|
si5351bx_clken &= ~(1 << 2);
|
||||||
|
i2cWrite(3, si5351bx_clken);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TXSubFreq(unsigned long P2)
|
||||||
|
{
|
||||||
|
i2cWrite(40, (P2 & 65280) >> 8);
|
||||||
|
i2cWrite(41, P2 & 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -5,9 +5,11 @@
|
|||||||
* 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(void){
|
||||||
if (digitalRead(FBUTTON) == HIGH)
|
if (digitalRead(FBUTTON) == HIGH)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
@@ -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,90 @@ 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 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 +128,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 +156,124 @@ 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, char offsetTtype) {
|
||||||
|
if ((displayOption1 & 0x01) == 0x01)
|
||||||
|
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||||
|
|
||||||
|
lcd.setCursor(lcdColumn, linenmbr);
|
||||||
|
|
||||||
|
for (byte i = eepromStartIndex; i <= eepromEndIndex; i++)
|
||||||
|
{
|
||||||
|
if (++lcdColumn <= LCD_MAX_COLUMN)
|
||||||
|
lcd.write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i));
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (byte i = lcdColumn; i < 16; i++) //Right Padding by Space
|
||||||
|
lcd.write(' ');
|
||||||
|
}
|
||||||
|
|
||||||
// short cut to print to the first line
|
// 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,44 +281,52 @@ void updateDisplay() {
|
|||||||
strcat(c, "B:");
|
strcat(c, "B:");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Fixed by Mitani Massaru (JE4SMQ)
|
||||||
|
if (isShiftDisplayCWFreq == 1)
|
||||||
//one mhz digit if less than 10 M, two digits if more
|
{
|
||||||
if (frequency < 10000000l){
|
if (cwMode == 1) //CWL
|
||||||
c[6] = ' ';
|
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
||||||
c[7] = b[0];
|
else if (cwMode == 2) //CWU
|
||||||
strcat(c, ".");
|
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
||||||
strncat(c, &b[1], 3);
|
|
||||||
strcat(c, ".");
|
|
||||||
strncat(c, &b[4], 3);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
strncat(c, b, 2);
|
|
||||||
strcat(c, ".");
|
|
||||||
strncat(c, &b[2], 3);
|
|
||||||
strcat(c, ".");
|
|
||||||
strncat(c, &b[5], 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inTx)
|
//display frequency
|
||||||
strcat(c, " TX");
|
for (int i = 15; i >= 6; i--) {
|
||||||
|
if (tmpFreq > 0) {
|
||||||
|
if (i == 12 || i == 8) c[i] = '.';
|
||||||
|
else {
|
||||||
|
c[i] = tmpFreq % 10 + 0x30;
|
||||||
|
tmpFreq /= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
c[i] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
//remarked by KD8CEC
|
||||||
|
//already RX/TX status display, and over index (16 x 2 LCD)
|
||||||
|
//if (inTx)
|
||||||
|
// strcat(c, " TX");
|
||||||
printLine(1, c);
|
printLine(1, c);
|
||||||
|
|
||||||
/*
|
byte diplayVFOLine = 1;
|
||||||
//now, the second line
|
if ((displayOption1 & 0x01) == 0x01)
|
||||||
memset(c, 0, sizeof(c));
|
diplayVFOLine = 0;
|
||||||
memset(b, 0, sizeof(b));
|
|
||||||
|
|
||||||
if (inTx)
|
if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) ||
|
||||||
strcat(c, "TX ");
|
(vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) {
|
||||||
else if (ritOn)
|
lcd.setCursor(5,diplayVFOLine);
|
||||||
strcpy(c, "RIT");
|
lcd.write((uint8_t)0);
|
||||||
|
}
|
||||||
strcpy(c, " \xff");
|
else if (isCWAutoMode == 2){
|
||||||
drawMeter(meter_reading);
|
lcd.setCursor(5,diplayVFOLine);
|
||||||
strcat(c, meter);
|
lcd.write(0x7E);
|
||||||
strcat(c, "\xff");
|
}
|
||||||
printLine2(c);*/
|
else
|
||||||
|
{
|
||||||
|
lcd.setCursor(5,diplayVFOLine);
|
||||||
|
lcd.write(":");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int enc_prev_state = 3;
|
int enc_prev_state = 3;
|
||||||
@@ -196,9 +358,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)
|
||||||
|
193
ubitx_20/ubitx_wspr.cpp
Normal file
193
ubitx_20/ubitx_wspr.cpp
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
/**********************************************************************************
|
||||||
|
WSPR SENDER for uBITX by KD8CEC
|
||||||
|
Some of the code that sends WSPR referenced the code in G3ZIL.
|
||||||
|
Thanks to G3ZIL for sharing great code.
|
||||||
|
|
||||||
|
Due to the limited memory of uBITX, I have implemented at least only a few of the codes in uBITX.
|
||||||
|
|
||||||
|
Thanks for testing
|
||||||
|
Beta Tester :
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
**********************************************************************************/
|
||||||
|
|
||||||
|
#include <arduino.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include "ubitx.h"
|
||||||
|
|
||||||
|
//begin of test
|
||||||
|
byte WsprToneCode[164];
|
||||||
|
|
||||||
|
long lastTime=0;
|
||||||
|
unsigned long TX_MSNB_P2; // Si5351 register MSNB_P2 PLLB for Tx
|
||||||
|
unsigned long TX_P2; // Variable values for MSNB_P2 which defines the frequencies for the data
|
||||||
|
|
||||||
|
extern int enc_read(void);
|
||||||
|
|
||||||
|
byte WsprMSGCount = 0;
|
||||||
|
#define PTT (A3)
|
||||||
|
|
||||||
|
#define WSPR_BAND1 401
|
||||||
|
|
||||||
|
extern uint8_t Wspr_Reg1[8]; //3, 4, 5, 6, 7
|
||||||
|
extern uint8_t Wspr_Reg2[8]; //2, 3, 4
|
||||||
|
|
||||||
|
void SendWSPRManage()
|
||||||
|
{
|
||||||
|
int knob = 0;
|
||||||
|
byte knobPosition = 0;
|
||||||
|
char isNeedDisplayInfo = 0;
|
||||||
|
char nowSelectedIndex = 0;
|
||||||
|
char nowWsprStep = 0; //0 : select Message, 1 : select band, 2 : send
|
||||||
|
char selectedWsprMessageIndex = -1;
|
||||||
|
char selectedWsprBandIndex = -1;
|
||||||
|
|
||||||
|
unsigned long WsprTXFreq = 0;
|
||||||
|
unsigned int WsprMultiChan = 0;
|
||||||
|
unsigned long prevFreq;
|
||||||
|
char loopIndex;
|
||||||
|
|
||||||
|
delay_background(500, 0);
|
||||||
|
|
||||||
|
//Readed WsprMSGCount, WsprTone
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
knob = enc_read();
|
||||||
|
|
||||||
|
if (knobPosition > 0 && knob < 0)
|
||||||
|
knobPosition--;
|
||||||
|
else if (knob > 0 && (knobPosition <= (nowWsprStep == 0 ? WsprMSGCount : WSPR_BAND_COUNT) * 10 -2))
|
||||||
|
knobPosition++;
|
||||||
|
|
||||||
|
nowSelectedIndex = knobPosition / 10;
|
||||||
|
|
||||||
|
if (nowWsprStep == 0) //select Message status
|
||||||
|
{
|
||||||
|
printLineF2(F("WSPR:"));
|
||||||
|
|
||||||
|
if (selectedWsprMessageIndex != nowSelectedIndex)
|
||||||
|
{
|
||||||
|
selectedWsprMessageIndex = nowSelectedIndex;
|
||||||
|
int wsprMessageBuffIndex = selectedWsprMessageIndex * 46;
|
||||||
|
|
||||||
|
//Display WSPR Name tag
|
||||||
|
printLineFromEEPRom(0, 6, wsprMessageBuffIndex, wsprMessageBuffIndex + 4, 1);
|
||||||
|
|
||||||
|
//Load WSPR Tonecode
|
||||||
|
//Read Tone Code
|
||||||
|
for (int i = 0; i < 41; i++)
|
||||||
|
{
|
||||||
|
byte readData = EEPROM.read(WSPR_MESSAGE1 + 5 + (wsprMessageBuffIndex) + i); //NAME TAG 5, MESSAGE 41 = 46
|
||||||
|
WsprToneCode[i * 4 + 0] = readData & 3;
|
||||||
|
WsprToneCode[i * 4 + 1] = (readData >> 2) & 3;
|
||||||
|
WsprToneCode[i * 4 + 2] = (readData >> 4) & 3;
|
||||||
|
WsprToneCode[i * 4 + 3] = (readData >> 6) & 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (btnDown())
|
||||||
|
{
|
||||||
|
nowWsprStep = 1; //Change Status to Select Band
|
||||||
|
knobPosition = 0;
|
||||||
|
nowSelectedIndex = 0;
|
||||||
|
delay_background(500, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (nowWsprStep == 1)
|
||||||
|
{
|
||||||
|
//printLineF2(F("Select Band"));
|
||||||
|
if (selectedWsprBandIndex != nowSelectedIndex)
|
||||||
|
{
|
||||||
|
selectedWsprBandIndex = nowSelectedIndex;
|
||||||
|
int bandBuffIndex = WSPR_BAND1 + selectedWsprBandIndex * 14;
|
||||||
|
|
||||||
|
EEPROM.get(bandBuffIndex, WsprTXFreq);
|
||||||
|
EEPROM.get(bandBuffIndex + 4, WsprMultiChan);
|
||||||
|
|
||||||
|
/*
|
||||||
|
//3, 4, 5, 6, 7
|
||||||
|
Wspr_Reg1[3] = EEPROM.read(bandBuffIndex + 6);
|
||||||
|
Wspr_Reg1[4] = EEPROM.read(bandBuffIndex + 7);
|
||||||
|
Wspr_Reg1[5] = EEPROM.read(bandBuffIndex + 8);
|
||||||
|
Wspr_Reg1[6] = EEPROM.read(bandBuffIndex + 9);
|
||||||
|
Wspr_Reg1[7] = EEPROM.read(bandBuffIndex + 10);
|
||||||
|
*/
|
||||||
|
for (loopIndex = 3; loopIndex < 8; loopIndex++)
|
||||||
|
Wspr_Reg1[loopIndex] = EEPROM.read(bandBuffIndex + loopIndex + 3);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Wspr_Reg2[2] = EEPROM.read(bandBuffIndex + 11);
|
||||||
|
Wspr_Reg2[3] = EEPROM.read(bandBuffIndex + 12);
|
||||||
|
Wspr_Reg2[4] = EEPROM.read(bandBuffIndex + 13);
|
||||||
|
*/
|
||||||
|
//2, 3, 4
|
||||||
|
for (loopIndex = 2; loopIndex < 5; loopIndex++)
|
||||||
|
Wspr_Reg2[loopIndex] = EEPROM.read(bandBuffIndex + loopIndex + 9);
|
||||||
|
|
||||||
|
TX_MSNB_P2 = ((unsigned long)Wspr_Reg1[5] & 0x0F) << 16 | ((unsigned long)Wspr_Reg1[6]) << 8 | Wspr_Reg1[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
ltoa(WsprTXFreq, b, DEC);
|
||||||
|
if (digitalRead(PTT) == 0)
|
||||||
|
strcpy(c, "SEND:");
|
||||||
|
else
|
||||||
|
strcpy(c, "PTT->");
|
||||||
|
|
||||||
|
strcat(c, b);
|
||||||
|
printLine1(c);
|
||||||
|
|
||||||
|
if (digitalRead(PTT) == 0)
|
||||||
|
{
|
||||||
|
//printLineF1(F("Transmitting"));
|
||||||
|
//SEND WSPR
|
||||||
|
//If you need to consider the Rit and Sprite modes, uncomment them below.
|
||||||
|
//remark = To reduce the size of the program
|
||||||
|
//prevFreq = frequency;
|
||||||
|
//frequency = WsprTXFreq;
|
||||||
|
startTx(TX_CW, 0);
|
||||||
|
setTXFilters(WsprTXFreq);
|
||||||
|
|
||||||
|
//Start WSPR
|
||||||
|
Set_WSPR_Param();
|
||||||
|
digitalWrite(CW_KEY, 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < 162; i++)
|
||||||
|
{ // Now this is the message loop
|
||||||
|
lastTime = millis(); // Store away the time when the last message symbol was sent
|
||||||
|
TX_P2 = TX_MSNB_P2 + WsprMultiChan * WsprToneCode[i]; // This represents the 1.46 Hz shift and is correct only for the bands specified in the array
|
||||||
|
TXSubFreq(TX_P2); // TX at the appropriate channel frequency for....
|
||||||
|
|
||||||
|
//if (btnDown())
|
||||||
|
// break;
|
||||||
|
|
||||||
|
while (millis() < lastTime + 683){} // .... 0,683 seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalWrite(CW_KEY, 0);
|
||||||
|
stopTx(); //call setFrequency -> recovery TX Filter
|
||||||
|
//frequency = prevFreq;
|
||||||
|
|
||||||
|
selectedWsprBandIndex = -1;
|
||||||
|
} //end of PTT Check
|
||||||
|
else if (btnDown())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //end of status check
|
||||||
|
|
||||||
|
//delay_background(50, 1);
|
||||||
|
} //end of while
|
||||||
|
}
|
||||||
|
|
BIN
ubitxmanager ubuntu.odt
Normal file
BIN
ubitxmanager ubuntu.odt
Normal file
Binary file not shown.
Reference in New Issue
Block a user