Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a60adaf2f | ||
|
|
02c0066df4 | ||
|
|
265188dc86 | ||
|
|
aee410fd19 | ||
|
|
16e173b109 | ||
|
|
d5db04ff0e | ||
|
|
0586bb75a7 |
@@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
uBITX - An Arduino sketch to control the uBITX transceiver
|
||||
Copyright (C) 2017, Ashhar Farhan
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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
|
||||
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
{project} Copyright (C) {year} {fullname}
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
@@ -1,207 +1,8 @@
|
||||
#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)
|
||||
# dspmeterv1
|
||||
Standalone Signal Analyzer (I2C Type Signal-Meter) for uBITX - Arduino Nano Version
|
||||
|
||||
#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.
|
||||
I do not claim any license for my code.
|
||||
You may use it in any way. I just hope this will be used for amateur radio.
|
||||
The other person's source code (CW Morse code) follows the original author's license.
|
||||
|
||||
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
|
||||
|
||||
Copyright (C) 2017, Ashhar Farhan
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
Ian KD8CEC
|
||||
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
FFTFunctions for Nextion LCD and Control MCU
|
||||
This code is for FFT and CW Decode.
|
||||
KD8CEC, Ian Lee
|
||||
-----------------------------------------------------------------------
|
||||
//The section on CW decode logic is specified at the bottom of this code.
|
||||
License : I follow the license of the previous code and I do not add any extra constraints.
|
||||
I hope that the Comment I made or the Comment of OZ1JHM will be maintained.
|
||||
**********************************************************************/
|
||||
#include <arduino.h>
|
||||
#include "i2cmeter1.h"
|
||||
|
||||
// Code Referency : http://paulbourke.net/miscellaneous/dft/
|
||||
// DFT, FFT Wiritten by Paul Bourke, June 1993
|
||||
void FFT(double *x,double *y, int n, long m)
|
||||
{
|
||||
long i,i1,j,k,i2,l,l1,l2;
|
||||
double c1,c2,tx,ty,t1,t2,u1,u2,z;
|
||||
short int dir = 0;
|
||||
|
||||
/* Do the bit reversal */
|
||||
i2 = n >> 1;
|
||||
j = 0;
|
||||
for (i=0;i<n-1;i++) {
|
||||
if (i < j) {
|
||||
tx = x[i];
|
||||
ty = y[i];
|
||||
x[i] = x[j];
|
||||
y[i] = y[j];
|
||||
x[j] = tx;
|
||||
y[j] = ty;
|
||||
}
|
||||
k = i2;
|
||||
while (k <= j) {
|
||||
j -= k;
|
||||
k >>= 1;
|
||||
}
|
||||
j += k;
|
||||
}
|
||||
|
||||
/* Compute the FFT */
|
||||
c1 = -1.0;
|
||||
c2 = 0.0;
|
||||
l2 = 1;
|
||||
|
||||
for (l=0;l<m;l++)
|
||||
{
|
||||
l1 = l2;
|
||||
l2 <<= 1;
|
||||
u1 = 1.0;
|
||||
u2 = 0.0;
|
||||
for (j=0;j<l1;j++)
|
||||
{
|
||||
for (i=j;i<n;i+=l2)
|
||||
{
|
||||
i1 = i + l1;
|
||||
t1 = u1 * x[i1] - u2 * y[i1];
|
||||
t2 = u1 * y[i1] + u2 * x[i1];
|
||||
x[i1] = x[i] - t1;
|
||||
y[i1] = y[i] - t2;
|
||||
x[i] += t1;
|
||||
y[i] += t2;
|
||||
}
|
||||
z = u1 * c1 - u2 * c2;
|
||||
u2 = u1 * c2 + u2 * c1;
|
||||
u1 = z;
|
||||
}
|
||||
c2 = sqrt((1.0 - c1) / 2.0);
|
||||
if (dir == 1)
|
||||
c2 = -c2;
|
||||
c1 = sqrt((1.0 + c1) / 2.0);
|
||||
}
|
||||
|
||||
/* Scaling for forward transform */
|
||||
/*
|
||||
if (dir == 1) {
|
||||
for (i=0;i<n;i++) {
|
||||
x[i] /= n;
|
||||
y[i] /= n;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
*/
|
||||
|
||||
//return(TRUE);
|
||||
}
|
||||
|
||||
double coeff;
|
||||
|
||||
void CalculateCoeff(uint8_t freqIndex)
|
||||
{
|
||||
float omega;
|
||||
int targetFrequency = freqIndex * 50 + 300;
|
||||
int k = (int) (0.5 + ((DECODE_MORSE_SAMPLESIZE * targetFrequency) / SAMPLE_PREQUENCY));
|
||||
omega = (2.0 * PI * k) / DECODE_MORSE_SAMPLESIZE;
|
||||
coeff = 2.0 * cos(omega);
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
//The CW Decode code refers to the site code below.
|
||||
//https://k2jji.org/2014/09/18/arduino-base-cw-decoder/
|
||||
//Some code has been modified, but the original comments remain intact.
|
||||
// code below is optimal for use in Arduino.
|
||||
//Thanks to OZ1JHM
|
||||
//KD8CEC
|
||||
//=====================================================================
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// CW Decoder made by Hjalmar Skovholm Hansen OZ1JHM VER 1.01 //
|
||||
// Feel free to change, copy or what ever you like but respect //
|
||||
// that license is http://www.gnu.org/copyleft/gpl.html //
|
||||
// Discuss and give great ideas on //
|
||||
// https://groups.yahoo.com/neo/groups/oz1jhm/conversations/messages //
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Read more here http://en.wikipedia.org/wiki/Goertzel_algorithm //
|
||||
// if you want to know about FFT the http://www.dspguide.com/pdfbook.htm //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//int magnitudelimit = 50;
|
||||
//int magnitudelimit_low = 50;
|
||||
int magnitudelimit = 30;
|
||||
int magnitudelimit_low = 30;
|
||||
char realstate = LOW;
|
||||
char realstatebefore = LOW;
|
||||
char filteredstate = LOW;
|
||||
char filteredstatebefore = LOW;
|
||||
long laststarttime = 0;
|
||||
int nbtime = 6; /// ms noise blanker
|
||||
|
||||
long starttimehigh;
|
||||
long highduration;
|
||||
long lasthighduration;
|
||||
long hightimesavg;
|
||||
long lowtimesavg;
|
||||
long startttimelow;
|
||||
long lowduration;
|
||||
|
||||
char code[20];
|
||||
uint8_t stop = LOW;
|
||||
int wpm;
|
||||
uint8_t cwDecodeHz = 9;
|
||||
|
||||
extern void SendCommandStr(char varIndex, char* sendValue);
|
||||
|
||||
void printascii(int asciinumber)
|
||||
{
|
||||
char rstDecode[4] = {0, 0, 0, 0};
|
||||
|
||||
if (asciinumber == 3)
|
||||
{
|
||||
|
||||
}
|
||||
else if (asciinumber == 4)
|
||||
{
|
||||
|
||||
}
|
||||
else if (asciinumber == 6)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
rstDecode[0] = asciinumber;
|
||||
}
|
||||
SendCommandStr('b', rstDecode);
|
||||
|
||||
//Serial.write(asciinumber);
|
||||
//if (writeCount++ > 20)
|
||||
//{
|
||||
//writeCount = 0;
|
||||
//Serial.println("");
|
||||
//}
|
||||
}
|
||||
|
||||
uint8_t docode()
|
||||
{
|
||||
if (strcmp(code,".-") == 0) printascii(65);
|
||||
if (strcmp(code,"-...") == 0) printascii(66);
|
||||
if (strcmp(code,"-.-.") == 0) printascii(67);
|
||||
if (strcmp(code,"-..") == 0) printascii(68);
|
||||
if (strcmp(code,".") == 0) printascii(69);
|
||||
if (strcmp(code,"..-.") == 0) printascii(70);
|
||||
if (strcmp(code,"--.") == 0) printascii(71);
|
||||
if (strcmp(code,"....") == 0) printascii(72);
|
||||
if (strcmp(code,"..") == 0) printascii(73);
|
||||
if (strcmp(code,".---") == 0) printascii(74);
|
||||
if (strcmp(code,"-.-") == 0) printascii(75);
|
||||
if (strcmp(code,".-..") == 0) printascii(76);
|
||||
if (strcmp(code,"--") == 0) printascii(77);
|
||||
if (strcmp(code,"-.") == 0) printascii(78);
|
||||
if (strcmp(code,"---") == 0) printascii(79);
|
||||
if (strcmp(code,".--.") == 0) printascii(80);
|
||||
if (strcmp(code,"--.-") == 0) printascii(81);
|
||||
if (strcmp(code,".-.") == 0) printascii(82);
|
||||
if (strcmp(code,"...") == 0) printascii(83);
|
||||
if (strcmp(code,"-") == 0) printascii(84);
|
||||
if (strcmp(code,"..-") == 0) printascii(85);
|
||||
if (strcmp(code,"...-") == 0) printascii(86);
|
||||
if (strcmp(code,".--") == 0) printascii(87);
|
||||
if (strcmp(code,"-..-") == 0) printascii(88);
|
||||
if (strcmp(code,"-.--") == 0) printascii(89);
|
||||
if (strcmp(code,"--..") == 0) printascii(90);
|
||||
|
||||
if (strcmp(code,".----") == 0) printascii(49);
|
||||
if (strcmp(code,"..---") == 0) printascii(50);
|
||||
if (strcmp(code,"...--") == 0) printascii(51);
|
||||
if (strcmp(code,"....-") == 0) printascii(52);
|
||||
if (strcmp(code,".....") == 0) printascii(53);
|
||||
if (strcmp(code,"-....") == 0) printascii(54);
|
||||
if (strcmp(code,"--...") == 0) printascii(55);
|
||||
if (strcmp(code,"---..") == 0) printascii(56);
|
||||
if (strcmp(code,"----.") == 0) printascii(57);
|
||||
if (strcmp(code,"-----") == 0) printascii(48);
|
||||
|
||||
if (strcmp(code,"..--..") == 0) printascii(63);
|
||||
if (strcmp(code,".-.-.-") == 0) printascii(46);
|
||||
if (strcmp(code,"--..--") == 0) printascii(44);
|
||||
if (strcmp(code,"-.-.--") == 0) printascii(33);
|
||||
if (strcmp(code,".--.-.") == 0) printascii(64);
|
||||
if (strcmp(code,"---...") == 0) printascii(58);
|
||||
if (strcmp(code,"-....-") == 0) printascii(45);
|
||||
if (strcmp(code,"-..-.") == 0) printascii(47);
|
||||
|
||||
if (strcmp(code,"-.--.") == 0) printascii(40);
|
||||
if (strcmp(code,"-.--.-") == 0) printascii(41);
|
||||
if (strcmp(code,".-...") == 0) printascii(95);
|
||||
if (strcmp(code,"...-..-") == 0) printascii(36);
|
||||
if (strcmp(code,"...-.-") == 0) printascii(62);
|
||||
if (strcmp(code,".-.-.") == 0) printascii(60);
|
||||
if (strcmp(code,"...-.") == 0) printascii(126);
|
||||
//////////////////
|
||||
// The specials //
|
||||
//////////////////
|
||||
if (strcmp(code,".-.-") == 0) printascii(3);
|
||||
if (strcmp(code,"---.") == 0) printascii(4);
|
||||
if (strcmp(code,".--.-") == 0) printascii(6);
|
||||
|
||||
}
|
||||
|
||||
void Decode_Morse(float magnitude)
|
||||
{
|
||||
//magnitudelimit auto Increase
|
||||
if (magnitude > magnitudelimit_low)
|
||||
{
|
||||
magnitudelimit = (magnitudelimit +((magnitude - magnitudelimit)/6)); /// moving average filter
|
||||
}
|
||||
|
||||
if (magnitudelimit < magnitudelimit_low)
|
||||
magnitudelimit = magnitudelimit_low;
|
||||
|
||||
if(magnitude > magnitudelimit*0.6) // just to have some space up
|
||||
realstate = HIGH;
|
||||
else
|
||||
realstate = LOW;
|
||||
|
||||
if (realstate != realstatebefore)
|
||||
laststarttime = millis();
|
||||
|
||||
if ((millis()-laststarttime) > nbtime)
|
||||
{
|
||||
if (realstate != filteredstate)
|
||||
{
|
||||
filteredstate = realstate;
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredstate != filteredstatebefore)
|
||||
{
|
||||
if (filteredstate == HIGH)
|
||||
{
|
||||
starttimehigh = millis();
|
||||
lowduration = (millis() - startttimelow);
|
||||
}
|
||||
|
||||
if (filteredstate == LOW)
|
||||
{
|
||||
startttimelow = millis();
|
||||
highduration = (millis() - starttimehigh);
|
||||
|
||||
if (highduration < (2*hightimesavg) || hightimesavg == 0)
|
||||
{
|
||||
hightimesavg = (highduration+hightimesavg+hightimesavg)/3; // now we know avg dit time ( rolling 3 avg)
|
||||
}
|
||||
|
||||
if (highduration > (5*hightimesavg) )
|
||||
{
|
||||
hightimesavg = highduration+hightimesavg; // if speed decrease fast ..
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// now we will check which kind of baud we have - dit or dah //
|
||||
// and what kind of pause we do have 1 - 3 or 7 pause //
|
||||
// we think that hightimeavg = 1 bit //
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
if (filteredstate != filteredstatebefore)
|
||||
{
|
||||
stop = LOW;
|
||||
if (filteredstate == LOW)
|
||||
{
|
||||
if (highduration < (hightimesavg*2) && highduration > (hightimesavg*0.6)) /// 0.6 filter out false dits
|
||||
{
|
||||
strcat(code,".");
|
||||
}
|
||||
if (highduration > (hightimesavg*2) && highduration < (hightimesavg*6))
|
||||
{
|
||||
strcat(code,"-");
|
||||
wpm = (wpm + (1200/((highduration)/3)))/2; //// the most precise we can do ;o)
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredstate == HIGH)
|
||||
{
|
||||
float lacktime = 1;
|
||||
if(wpm > 25)lacktime=1.0; /// when high speeds we have to have a little more pause before new letter or new word
|
||||
if(wpm > 30)lacktime=1.2;
|
||||
if(wpm > 35)lacktime=1.5;
|
||||
|
||||
if (lowduration > (hightimesavg*(2*lacktime)) && lowduration < hightimesavg*(5*lacktime)) // letter space
|
||||
{
|
||||
docode();
|
||||
code[0] = '\0';
|
||||
}
|
||||
if (lowduration >= hightimesavg*(5*lacktime))
|
||||
{ // word space
|
||||
docode();
|
||||
code[0] = '\0';
|
||||
printascii(32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((millis() - startttimelow) > (highduration * 6) && stop == LOW)
|
||||
{
|
||||
docode();
|
||||
code[0] = '\0';
|
||||
stop = HIGH;
|
||||
}
|
||||
|
||||
/*
|
||||
if(filteredstate == HIGH)
|
||||
{
|
||||
digitalWrite(ledPin, HIGH);
|
||||
tone(audioOutPin,target_freq);
|
||||
}
|
||||
else
|
||||
{
|
||||
digitalWrite(ledPin, LOW);
|
||||
noTone(audioOutPin);
|
||||
}
|
||||
*/
|
||||
|
||||
realstatebefore = realstate;
|
||||
lasthighduration = highduration;
|
||||
filteredstatebefore = filteredstate;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
Configuration file for Nextion LCD and Control MCU
|
||||
The parameter can be set according to the CPU used.
|
||||
|
||||
KD8CEC, Ian Lee
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include <arduino.h>
|
||||
|
||||
//================================================================
|
||||
//COMMUNICATION SECTION
|
||||
//================================================================
|
||||
#define USE_SW_SERIAL
|
||||
|
||||
extern void SWSerial_Write(uint8_t b);
|
||||
extern void SWSerial_Print(uint8_t *b);
|
||||
|
||||
#ifdef USE_SW_SERIAL
|
||||
extern void SWSerial_Begin(long speedBaud);
|
||||
extern int SWSerial_Available(void);
|
||||
extern int SWSerial_Read(void);
|
||||
#else
|
||||
|
||||
#define PRINT_MAX_LENGTH 30
|
||||
#endif
|
||||
|
||||
//================================================================
|
||||
//FFT and Decode Morse
|
||||
//================================================================
|
||||
#define FFTSIZE 64
|
||||
#define SAMPLE_PREQUENCY 6000
|
||||
#define SAMPLESIZE (FFTSIZE * 2)
|
||||
#define DECODE_MORSE_SAMPLESIZE 48
|
||||
|
||||
extern uint8_t cwDecodeHz;
|
||||
extern int magnitudelimit_low;
|
||||
|
||||
//================================================================
|
||||
//EEPROM Section
|
||||
//================================================================
|
||||
#define MAX_FORWARD_BUFF_LENGTH 128
|
||||
#define EEPROM_DSPTYPE 100
|
||||
#define EEPROM_SMETER_UART 111
|
||||
#define EEPROM_SMETER_TIME 112
|
||||
|
||||
#define EEPROM_CW_FREQ 120
|
||||
//#define EEPROM_CW_MAG_LIMIT 121
|
||||
#define EEPROM_CW_MAG_LOW 122
|
||||
#define EEPROM_CW_NBTIME 126
|
||||
#define EEPROM_RTTYDECODEHZ 130
|
||||
|
||||
//================================================================
|
||||
//DEFINE for I2C Command
|
||||
//================================================================
|
||||
//S-Meter Address
|
||||
#define I2CMETER_ADDR 0x58 //changed from 0x6A
|
||||
//VALUE TYPE============================================
|
||||
//Signal
|
||||
#define I2CMETER_CALCS 0x59 //Calculated Signal Meter
|
||||
#define I2CMETER_UNCALCS 0x58 //Uncalculated Signal Meter
|
||||
|
||||
//Power
|
||||
#define I2CMETER_CALCP 0x57 //Calculated Power Meter
|
||||
#define I2CMETER_UNCALCP 0x56 //UnCalculated Power Meter
|
||||
|
||||
//SWR
|
||||
#define I2CMETER_CALCR 0x55 //Calculated SWR Meter
|
||||
#define I2CMETER_UNCALCR 0x54 //Uncalculated SWR Meter
|
||||
|
||||
#define SIGNAL_METER_ADC A7
|
||||
#define POWER_METER_ADC A3
|
||||
#define SWR_METER_ADC A2
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
Softserial for Nextion LCD and Control MCU
|
||||
KD8CEC, Ian Lee
|
||||
-----------------------------------------------------------------------
|
||||
It is a library rewritten in C format based on SoftwareSerial.c.
|
||||
I tried to use as much as possible without modifying the SoftwareSerial.
|
||||
But eventually I had to modify the code.
|
||||
|
||||
I rewrote it in C for the following reasons.
|
||||
- Problems occurred when increasing Program Size and Program Memory
|
||||
- We had to reduce the program size.
|
||||
Of course, Software Serial is limited to one.
|
||||
- reduce the steps for transmitting and receiving
|
||||
|
||||
useage
|
||||
extern void SWSerial_Begin(long speedBaud);
|
||||
extern void SWSerial_Write(uint8_t b);
|
||||
extern int SWSerial_Available(void);
|
||||
extern int SWSerial_Read(void);
|
||||
extern void SWSerial_Print(uint8_t *b);
|
||||
|
||||
If you use Softwreserial library instead of this library, you can modify the code as shown below.
|
||||
I kept the function name of SoftwareSerial so you only need to modify a few lines of code.
|
||||
|
||||
define top of source code
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial sSerial(10, 11); // RX, TX
|
||||
|
||||
replace source code
|
||||
SWSerial_Begin to sSerial.begin
|
||||
SWSerial_Write to sSerial.write
|
||||
SWSerial_Available to sSerial.available
|
||||
SWSerial_Read to sSerial.read
|
||||
|
||||
KD8CEC, Ian Lee
|
||||
-----------------------------------------------------------------------
|
||||
License
|
||||
All licenses for the source code are subject to the license of the original source SoftwareSerial Library.
|
||||
However, if you use or modify this code, please keep the all comments in this source code.
|
||||
KD8CEC
|
||||
-----------------------------------------------------------------------
|
||||
License from SoftwareSerial
|
||||
-----------------------------------------------------------------------
|
||||
SoftwareSerial.cpp (formerly NewSoftSerial.cpp) -
|
||||
Multi-instance software serial library for Arduino/Wiring
|
||||
-- Interrupt-driven receive and other improvements by ladyada
|
||||
(http://ladyada.net)
|
||||
-- Tuning, circular buffer, derivation from class Print/Stream,
|
||||
multi-instance support, porting to 8MHz processors,
|
||||
various optimizations, PROGMEM delay tables, inverse logic and
|
||||
direct port writing by Mikal Hart (http://www.arduiniana.org)
|
||||
-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
|
||||
-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
|
||||
-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
The latest version of this library can always be found at
|
||||
http://arduiniana.org.
|
||||
*/
|
||||
#include "i2cmeter1.h"
|
||||
|
||||
#ifdef USE_SW_SERIAL
|
||||
//================================================================
|
||||
//Public Variable
|
||||
//================================================================
|
||||
#define TX_PIN 9
|
||||
#define RX_PIN 8
|
||||
#define _SS_MAX_RX_BUFF 35 // RX buffer size
|
||||
#define PRINT_MAX_LENGTH 30
|
||||
|
||||
//================================================================
|
||||
//Internal Variable from SoftwareSerial.c and SoftwareSerial.h
|
||||
//================================================================
|
||||
//variable from softwareserial.c and softwareserial.h
|
||||
static uint8_t swr_receive_buffer[_SS_MAX_RX_BUFF];
|
||||
|
||||
volatile uint8_t *_transmitPortRegister; //Write Port Register
|
||||
uint8_t transmit_RegMask; //use Mask bit 1
|
||||
uint8_t transmit_InvMask; //use mask bit 0
|
||||
|
||||
volatile uint8_t *_receivePortRegister; //Read Port Register
|
||||
uint8_t _receiveBitMask;
|
||||
|
||||
//delay value for Bit
|
||||
uint16_t _tx_delay;
|
||||
|
||||
//delay value for Receive
|
||||
uint16_t _rx_delay_stopbit;
|
||||
uint16_t _rx_delay_centering;
|
||||
uint16_t _rx_delay_intrabit;
|
||||
|
||||
//Customize for uBITX Protocol
|
||||
int8_t receiveIndex = 0;
|
||||
int8_t receivedCommandLength = 0;
|
||||
int8_t ffCount = 0;
|
||||
|
||||
//Values for Receive Buffer
|
||||
//uint16_t _buffer_overflow;
|
||||
//static volatile uint8_t _receive_buffer_head;
|
||||
//static volatile uint8_t _receive_buffer_tail;
|
||||
|
||||
//Values for Interrupt (check Start Bit)
|
||||
volatile uint8_t *_pcint_maskreg;
|
||||
uint8_t _pcint_maskvalue;
|
||||
|
||||
//================================================================
|
||||
//Internal Function from SoftwareSerial.c
|
||||
//================================================================
|
||||
uint16_t subtract_cap(uint16_t num, uint16_t sub)
|
||||
{
|
||||
if (num > sub)
|
||||
return num - sub;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline void tunedDelay(uint16_t delay)
|
||||
{
|
||||
_delay_loop_2(delay);
|
||||
}
|
||||
|
||||
void setRxIntMsk(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
*_pcint_maskreg |= _pcint_maskvalue;
|
||||
else
|
||||
*_pcint_maskreg &= ~_pcint_maskvalue;
|
||||
}
|
||||
|
||||
uint8_t rx_pin_read()
|
||||
{
|
||||
return *_receivePortRegister & _receiveBitMask;
|
||||
}
|
||||
|
||||
//
|
||||
// The receive routine called by the interrupt handler
|
||||
//
|
||||
void softSerail_Recv()
|
||||
{
|
||||
#if GCC_VERSION < 40302
|
||||
// Work-around for avr-gcc 4.3.0 OSX version bug
|
||||
// Preserve the registers that the compiler misses
|
||||
// (courtesy of Arduino forum user *etracer*)
|
||||
asm volatile(
|
||||
"push r18 \n\t"
|
||||
"push r19 \n\t"
|
||||
"push r20 \n\t"
|
||||
"push r21 \n\t"
|
||||
"push r22 \n\t"
|
||||
"push r23 \n\t"
|
||||
"push r26 \n\t"
|
||||
"push r27 \n\t"
|
||||
::);
|
||||
#endif
|
||||
|
||||
uint8_t d = 0;
|
||||
|
||||
// If RX line is high, then we don't see any start bit
|
||||
// so interrupt is probably not for us
|
||||
if (!rx_pin_read()) //Start Bit
|
||||
{
|
||||
// Disable further interrupts during reception, this prevents
|
||||
// triggering another interrupt directly after we return, which can
|
||||
// cause problems at higher baudrates.
|
||||
setRxIntMsk(false);
|
||||
|
||||
// Wait approximately 1/2 of a bit width to "center" the sample
|
||||
tunedDelay(_rx_delay_centering);
|
||||
|
||||
// Read each of the 8 bits
|
||||
for (uint8_t i=8; i > 0; --i)
|
||||
{
|
||||
tunedDelay(_rx_delay_intrabit);
|
||||
d >>= 1;
|
||||
|
||||
if (rx_pin_read())
|
||||
d |= 0x80;
|
||||
}
|
||||
|
||||
if (receivedCommandLength == 0) //check Already Command
|
||||
{
|
||||
//Set Received Data
|
||||
swr_receive_buffer[receiveIndex++] = d;
|
||||
|
||||
//Finded Command
|
||||
if (d == 0x73 && ffCount > 1 && receiveIndex > 6)
|
||||
{
|
||||
receivedCommandLength = receiveIndex;
|
||||
receiveIndex = 0;
|
||||
ffCount = 0;
|
||||
}
|
||||
else if (receiveIndex > _SS_MAX_RX_BUFF)
|
||||
{
|
||||
//Buffer Overflow
|
||||
receiveIndex = 0;
|
||||
ffCount = 0;
|
||||
}
|
||||
else if (d == 0xFF)
|
||||
{
|
||||
ffCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ffCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// skip the stop bit
|
||||
tunedDelay(_rx_delay_stopbit);
|
||||
|
||||
// Re-enable interrupts when we're sure to be inside the stop bit
|
||||
setRxIntMsk(true);
|
||||
}
|
||||
|
||||
#if GCC_VERSION < 40302
|
||||
// Work-around for avr-gcc 4.3.0 OSX version bug
|
||||
// Restore the registers that the compiler misses
|
||||
asm volatile(
|
||||
"pop r27 \n\t"
|
||||
"pop r26 \n\t"
|
||||
"pop r23 \n\t"
|
||||
"pop r22 \n\t"
|
||||
"pop r21 \n\t"
|
||||
"pop r20 \n\t"
|
||||
"pop r19 \n\t"
|
||||
"pop r18 \n\t"
|
||||
::);
|
||||
#endif
|
||||
}
|
||||
|
||||
ISR(PCINT0_vect)
|
||||
{
|
||||
softSerail_Recv();
|
||||
}
|
||||
|
||||
//================================================================
|
||||
//Public Function from SoftwareSerial.c and modified and create
|
||||
//================================================================
|
||||
// Read data from buffer
|
||||
void SWSerial_Read(uint8_t * receive_cmdBuffer)
|
||||
{
|
||||
for (int i = 0; i < receivedCommandLength; i++)
|
||||
receive_cmdBuffer[i] = swr_receive_buffer[i];
|
||||
}
|
||||
|
||||
void SWSerial_Write(uint8_t b)
|
||||
{
|
||||
volatile uint8_t *reg = _transmitPortRegister;
|
||||
uint8_t oldSREG = SREG;
|
||||
uint16_t delay = _tx_delay;
|
||||
|
||||
cli(); // turn off interrupts for a clean txmit
|
||||
|
||||
// Write the start bit
|
||||
*reg &= transmit_InvMask;
|
||||
|
||||
tunedDelay(delay);
|
||||
|
||||
// Write each of the 8 bits
|
||||
for (uint8_t i = 8; i > 0; --i)
|
||||
{
|
||||
if (b & 1) // choose bit
|
||||
*reg |= transmit_RegMask; // send 1
|
||||
else
|
||||
*reg &= transmit_InvMask; // send 0
|
||||
|
||||
tunedDelay(delay);
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
// restore pin to natural state
|
||||
*reg |= transmit_RegMask;
|
||||
|
||||
SREG = oldSREG; // turn interrupts back on
|
||||
tunedDelay(_tx_delay);
|
||||
}
|
||||
|
||||
void SWSerial_Print(uint8_t *b)
|
||||
{
|
||||
for (int i = 0; i < PRINT_MAX_LENGTH; i++)
|
||||
{
|
||||
if (b[i] == 0x00)
|
||||
break;
|
||||
else
|
||||
SWSerial_Write(b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void SWSerial_Begin(long speedBaud)
|
||||
{
|
||||
//INT TX_PIN
|
||||
digitalWrite(TX_PIN, HIGH);
|
||||
pinMode(TX_PIN, OUTPUT);
|
||||
transmit_RegMask = digitalPinToBitMask(TX_PIN); //use Bit 1
|
||||
transmit_InvMask = ~digitalPinToBitMask(TX_PIN); //use Bit 0
|
||||
_transmitPortRegister = portOutputRegister(digitalPinToPort(TX_PIN));
|
||||
|
||||
//INIT RX_PIN
|
||||
pinMode(RX_PIN, INPUT);
|
||||
digitalWrite(RX_PIN, HIGH); // pullup for normal logic!
|
||||
_receiveBitMask = digitalPinToBitMask(RX_PIN);
|
||||
_receivePortRegister = portInputRegister(digitalPinToPort(RX_PIN));
|
||||
|
||||
//Set Values
|
||||
uint16_t bit_delay = (F_CPU / speedBaud) / 4;
|
||||
_tx_delay = subtract_cap(bit_delay, 15 / 4);
|
||||
|
||||
if (digitalPinToPCICR(RX_PIN))
|
||||
{
|
||||
_rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4);
|
||||
_rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4);
|
||||
_rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4);
|
||||
*digitalPinToPCICR(RX_PIN) |= _BV(digitalPinToPCICRbit(RX_PIN));
|
||||
_pcint_maskreg = digitalPinToPCMSK(RX_PIN);
|
||||
_pcint_maskvalue = _BV(digitalPinToPCMSKbit(RX_PIN));
|
||||
|
||||
tunedDelay(_tx_delay); // if we were low this establishes the end
|
||||
}
|
||||
|
||||
//Start Listen
|
||||
setRxIntMsk(true);
|
||||
}
|
||||
#else
|
||||
void SWSerial_Write(uint8_t b)
|
||||
{
|
||||
Serial.write(b);
|
||||
//Serial.flush();
|
||||
}
|
||||
|
||||
void SWSerial_Print(uint8_t *b)
|
||||
{
|
||||
for (int i = 0; i < PRINT_MAX_LENGTH; i++)
|
||||
{
|
||||
if (b[i] == 0x00)
|
||||
break;
|
||||
else
|
||||
SWSerial_Write(b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,843 +0,0 @@
|
||||
/*************************************************************************
|
||||
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
|
||||
{
|
||||
//Special Command
|
||||
if (eepromStartIndex == 13131) //Magic Key
|
||||
{
|
||||
if (write1Byte == 0x51) //Restart
|
||||
{
|
||||
asm volatile (" jmp 0");
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
const byte anlogPinIndex[6] = {A0, A1, A2, A3, A6, A7};
|
||||
|
||||
//Read ADC Value by uBITX Manager Software
|
||||
void ReadADCValue(void)
|
||||
{
|
||||
//ADC MAP for uBITX
|
||||
int readedADCValue;
|
||||
//5BYTES
|
||||
//CAT_BUFF[0] [1] [2] [3] [4] //4 COMMAND
|
||||
//0 READ ADDRESS
|
||||
readedADCValue = analogRead(anlogPinIndex[CAT_BUFF[0]]);
|
||||
CAT_BUFF[0] = readedADCValue >> 8;
|
||||
CAT_BUFF[1] = readedADCValue;
|
||||
SendCatData(2);
|
||||
Serial.write(ACK);
|
||||
}
|
||||
|
||||
void SetIFSValue(void)
|
||||
{
|
||||
//Set IFShift Value
|
||||
isIFShift = CAT_BUFF[0];
|
||||
ifShiftValue = CAT_BUFF[1] + CAT_BUFF[2] * 256;
|
||||
setFrequency(frequency);
|
||||
SetCarrierFreq();
|
||||
updateLine2Buffer(1); //option, perhap not need
|
||||
Serial.write(ACK);
|
||||
}
|
||||
|
||||
//void CatRxStatus(byte fromType)
|
||||
void CatRxStatus(void) //for remove warning
|
||||
{
|
||||
byte sMeterValue = 1;
|
||||
|
||||
/*
|
||||
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 0xDD: //Read uBITX ADC Data
|
||||
ReadADCValue(); //Call by uBITX Manager Program
|
||||
break;
|
||||
|
||||
case 0xDE: //IF-Shift Control by CAT
|
||||
SetIFSValue(); //
|
||||
break;
|
||||
|
||||
case 0xE7 : //Read RX Status
|
||||
CatRxStatus();
|
||||
break;
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -1,423 +0,0 @@
|
||||
/*************************************************************************
|
||||
KD8CEC's Memory Keyer for HAM
|
||||
|
||||
This source code is written for All amateur radio operator,
|
||||
I have not had amateur radio communication for a long time. CW has been
|
||||
around for a long time, and I do not know what kind of keyer and keying
|
||||
software is fashionable. So I implemented the functions I need mainly.
|
||||
|
||||
To minimize the use of memory space, we used bitwise operations.
|
||||
For the alphabet, I put Morsecode in 1 byte. The front 4Bit is the length
|
||||
and the 4Bit is the Morse code. Because the number is fixed in length,
|
||||
there is no separate length information. The 5Bit on the right side is
|
||||
the Morse code.
|
||||
|
||||
I wrote this code myself, so there is no license restriction.
|
||||
So this code allows anyone to write with confidence.
|
||||
But keep it as long as the original author of the code.
|
||||
DE Ian KD8CEC
|
||||
-----------------------------------------------------------------------------
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
//27 + 10 + 18 + 1(SPACE) = //56
|
||||
const PROGMEM uint8_t cwAZTable[27] = {0b00100100 , 0b01001000 , 0b01001010 , 0b00111000 , 0b00010000, 0b01000010, 0b00111100, 0b01000000 , //A ~ H
|
||||
0b00100000, 0b01000111 ,0b00111010, 0b01000100, 0b00101100, 0b00101000 , 0b00111110, 0b01000110, 0b01001101, 0b00110100, //I ~ R
|
||||
0b00110000, 0b00011000, 0b00110010, 0b01000001, 0b00110110, 0b01001001, 0b01001011, 0b01001100}; //S ~ Z
|
||||
PGM_P pCwAZTable = reinterpret_cast<PGM_P>(cwAZTable);
|
||||
|
||||
const PROGMEM uint8_t cw09Table[27] = {0b00011111, 0b00001111, 0b00000111, 0b00000011, 0b00000001, 0b00000000, 0b00010000, 0b00011000, 0b00011100, 0b00011110};
|
||||
PGM_P pcw09Table = reinterpret_cast<PGM_P>(cw09Table);
|
||||
|
||||
//# : AR, ~:BT, [:AS, ]:SK, ^:KN
|
||||
const PROGMEM uint8_t cwSymbolIndex[] = {'.', ',', '?', '"', '!', '/', '(', ')', '&', ':', ';', '=', '+', '-', '_', '\'', '@', '#', '~', '[', ']', '^' };
|
||||
PGM_P pCwSymbolIndex = reinterpret_cast<PGM_P>(cwSymbolIndex);
|
||||
|
||||
const PROGMEM uint8_t cwSymbolTable[] = {0b11010101, 0b11110011, 0b11001100, 0b11011110, 0b11101011, 0b10100100, 0b10101100, 0b11101101, 0b10010000, 0b11111000, 0b11101010, 0b10100010, 0b10010100, 0b11100001, 0b11001101, 0b11010010, 0b11011010, 0b10010100, 0b10100010, 0b10010000, 0b11000101, 0b10101100};
|
||||
PGM_P pCwSymbolTable = reinterpret_cast<PGM_P>(cwSymbolTable);
|
||||
////const PROGMEM uint8_t cwSymbolLength[] = {6, 6, 6, 6, 6, 5, 5, 6, 5, 6, 6, 5, 5, 6, 6, 6, 6, 5, 5, 5, 6, 5};
|
||||
|
||||
// ":(Start"), ':(End "), >: My callsign, <:QSO Callsign (Second Callsign), #:AR, ~:BT, [:AS, ]:SK
|
||||
|
||||
byte knobPosition = 0;
|
||||
//byte cwTextData[30]; //Maximum 30 Remarked by KD8CE -> Direct Read EEPROM
|
||||
byte autoCWSendCharEndIndex = 0;
|
||||
byte autoCWSendCharIndex = 0;
|
||||
unsigned long autoCWbeforeTime = 0; //for interval time between chars
|
||||
byte pttBeforeStatus = 1; //PTT : default high
|
||||
byte isKeyStatusAfterCWStart = 0; //0 : Init, 1 : Keyup after auto CW Start, 2 : Keydown after
|
||||
byte selectedCWTextIndex = 0;
|
||||
unsigned long autoCWKeydownCheckTime = 0; //for interval time between chars
|
||||
byte changeReserveStatus = 0;
|
||||
byte isAutoCWHold = 0; //auto CW Pause => Manual Keying => auto
|
||||
|
||||
void autoSendPTTCheck()
|
||||
{
|
||||
if (isCWAutoMode == 2) { //Sending Mode
|
||||
//check PTT Button
|
||||
//short Press => reservation or cancel
|
||||
//long Press => Hold
|
||||
if (digitalRead(PTT) == LOW)
|
||||
{
|
||||
//if (isKeyStatusAfterCWStart == 0) //Yet Press PTT from start TX
|
||||
//{
|
||||
//}
|
||||
|
||||
if (isKeyStatusAfterCWStart == 1) //while auto cw send, ptt up and ptt down again
|
||||
{
|
||||
//Start Time
|
||||
autoCWKeydownCheckTime = millis() + 200; //Long push time
|
||||
isKeyStatusAfterCWStart = 2; //Change status => ptt down agian
|
||||
}
|
||||
else if (isKeyStatusAfterCWStart == 2 && autoCWKeydownCheckTime < millis())
|
||||
{
|
||||
//Hold Mode
|
||||
isAutoCWHold = 1;
|
||||
isKeyStatusAfterCWStart = 3;
|
||||
}
|
||||
else if (isKeyStatusAfterCWStart == 3)
|
||||
{
|
||||
autoCWKeydownCheckTime = millis() + 200;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//PTT UP
|
||||
if (isKeyStatusAfterCWStart == 2) //0 (down before cw start) -> 1 (up while cw sending) -> 2 (down while cw sending)
|
||||
{
|
||||
if (autoCWKeydownCheckTime > millis()) //Short : Reservation or cancel Next Text
|
||||
{
|
||||
if (autoCWSendReservCount == 0 ||
|
||||
(autoCWSendReservCount < AUTO_CW_RESERVE_MAX &&
|
||||
autoCWSendReserv[autoCWSendReservCount - 1] != selectedCWTextIndex))
|
||||
{
|
||||
//Reserve
|
||||
autoCWSendReserv[autoCWSendReservCount++] = selectedCWTextIndex;
|
||||
changeReserveStatus = 1;
|
||||
}
|
||||
else if (autoCWSendReservCount > 0 && autoCWSendReserv[autoCWSendReservCount - 1] == selectedCWTextIndex)
|
||||
{
|
||||
autoCWSendReservCount--;
|
||||
changeReserveStatus = 1;
|
||||
}
|
||||
} // end of Short Key up
|
||||
}
|
||||
else if (isKeyStatusAfterCWStart == 3) //play from Hold (pause Auto CW Send)
|
||||
{
|
||||
isAutoCWHold = 0;
|
||||
}
|
||||
|
||||
isKeyStatusAfterCWStart = 1; //Change status => ptt up (while cw send mode)
|
||||
} //end of PTT UP
|
||||
}
|
||||
}
|
||||
|
||||
//Send 1 char
|
||||
void sendCWChar(char cwKeyChar)
|
||||
{
|
||||
byte sendBuff[7];
|
||||
byte i, j, charLength;
|
||||
byte tmpChar;
|
||||
|
||||
//For Macrofunction
|
||||
//replace > and < to My callsign, qso callsign, use recursive function call
|
||||
if (cwKeyChar == '>' || cwKeyChar == '<')
|
||||
{
|
||||
uint16_t callsignStartIndex = 0;
|
||||
uint16_t callsignEndIndex = 0;
|
||||
|
||||
if (cwKeyChar == '>') //replace my callsign
|
||||
{
|
||||
if (userCallsignLength > 0)
|
||||
{
|
||||
callsignStartIndex = 0;
|
||||
callsignEndIndex = userCallsignLength;
|
||||
}
|
||||
}
|
||||
else if (cwKeyChar == '<') //replace qso callsign
|
||||
{
|
||||
//ReadLength
|
||||
callsignEndIndex = EEPROM.read(CW_STATION_LEN);
|
||||
if (callsignEndIndex > 0)
|
||||
{
|
||||
callsignStartIndex = CW_STATION_LEN - callsignEndIndex - USER_CALLSIGN_DAT;
|
||||
callsignEndIndex = callsignStartIndex + callsignEndIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if (callsignStartIndex == 0 && callsignEndIndex == 0)
|
||||
return;
|
||||
|
||||
for (uint16_t i = callsignStartIndex; i <= callsignEndIndex; i++)
|
||||
{
|
||||
sendCWChar(EEPROM.read(USER_CALLSIGN_DAT + i));
|
||||
autoSendPTTCheck(); //for reserve and cancel next CW Text
|
||||
if (changeReserveStatus == 1)
|
||||
{
|
||||
changeReserveStatus = 0;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
if (i < callsignEndIndex) delay_background(cwSpeed * 3, 4); //
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (cwKeyChar >= 'A' && cwKeyChar <= 'Z') //Encode Char by KD8CEC
|
||||
{
|
||||
tmpChar = pgm_read_byte(pCwAZTable + (cwKeyChar - 'A'));
|
||||
charLength = (tmpChar >> 4) & 0x0F;
|
||||
for (i = 0; i < charLength; i++)
|
||||
sendBuff[i] = (tmpChar << i) & 0x08;
|
||||
}
|
||||
else if (cwKeyChar >= '0' && cwKeyChar <= '9')
|
||||
{
|
||||
charLength = 5;
|
||||
for (i = 0; i < charLength; i++)
|
||||
sendBuff[i] = (pgm_read_byte(pcw09Table + (cwKeyChar - '0')) << i) & 0x10;
|
||||
}
|
||||
else if (cwKeyChar == ' ')
|
||||
{
|
||||
charLength = 0;
|
||||
delay_background(cwSpeed * 4, 4); //7 -> basic interval is 3
|
||||
}
|
||||
else if (cwKeyChar == '$') //7 digit
|
||||
{
|
||||
charLength = 7;
|
||||
for (i = 0; i < 7; i++)
|
||||
sendBuff[i] = (0b00010010 << i) & 0x80; //...1..1
|
||||
}
|
||||
else
|
||||
{
|
||||
//symbol
|
||||
for (i = 0; i < 22; i++)
|
||||
{
|
||||
if (pgm_read_byte(pCwSymbolIndex + i) == cwKeyChar)
|
||||
{
|
||||
tmpChar = pgm_read_byte(pCwSymbolTable + i);
|
||||
charLength = ((tmpChar >> 6) & 0x03) + 3;
|
||||
|
||||
for (j = 0; j < charLength; j++)
|
||||
sendBuff[j] = (tmpChar << (j + 2)) & 0x80;
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
charLength = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < charLength; i++)
|
||||
{
|
||||
cwKeydown();
|
||||
if (sendBuff[i] == 0)
|
||||
delay_background(cwSpeed, 4);
|
||||
else
|
||||
delay_background(cwSpeed * 3, 4);
|
||||
cwKeyUp();
|
||||
if (i != charLength -1)
|
||||
delay_background(cwSpeed, 4);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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;
|
||||
|
||||
Display_AutoKeyTextIndex(selectedCWTextIndex);
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
/*************************************************************************
|
||||
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/>.
|
||||
**************************************************************************/
|
||||
#include <Arduino.h> //for Linux, On Linux it is case sensitive.
|
||||
|
||||
//==============================================================================
|
||||
// Compile Option
|
||||
//==============================================================================
|
||||
//Depending on the type of LCD mounted on the uBITX, uncomment one of the options below.
|
||||
//You must select only one.
|
||||
#define UBITX_DISPLAY_LCD1602P //LCD mounted on unmodified uBITX
|
||||
//#define UBITX_DISPLAY_LCD1602I //I2C type 16 x 02 LCD
|
||||
//#define UBITX_DISPLAY_LCD1602I_DUAL
|
||||
//#define UBITX_DISPLAY_LCD2004P //24 x 04 LCD (Parallel)
|
||||
//#define UBITX_DISPLAY_LCD2004I //I2C type 24 x 04 LCD
|
||||
|
||||
#define I2C_LCD_MASTER_ADDRESS_DEFAULT 0x3F //0x27 //DEFAULT, if Set I2C Address by uBITX Manager, read from EEProm
|
||||
#define I2C_LCD_SECOND_ADDRESS_DEFAULT 0x27 //0x27 //only using Dual LCD Mode
|
||||
|
||||
#define EXTEND_KEY_GROUP1 //MODE, BAND(-), BAND(+), STEP
|
||||
//#define EXTEND_KEY_GROUP2 //Numeric (0~9), Point(.), Enter //Not supported in Version 1.0x
|
||||
|
||||
#define ENABLE_FACTORYALIGN
|
||||
//#define ENABLE_ADCMONITOR //Starting with Version 1.07, you can read ADC values directly from uBITX Manager. So this function is not necessary.
|
||||
|
||||
extern byte I2C_LCD_MASTER_ADDRESS; //0x27 //if Set I2C Address by uBITX Manager, read from EEProm
|
||||
extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode
|
||||
|
||||
#define SMeterLatency 3 //1 is 0.25 sec
|
||||
|
||||
#ifdef UBITX_DISPLAY_LCD1602I
|
||||
#define USE_I2C_LCD
|
||||
#elif defined(UBITX_DISPLAY_LCD1602I_DUAL)
|
||||
#define USE_I2C_LCD
|
||||
#elif defined(UBITX_DISPLAY_LCD2004I)
|
||||
#define USE_I2C_LCD
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
// Hardware, Define PIN Usage
|
||||
//==============================================================================
|
||||
/**
|
||||
* We need to carefully pick assignment of pin for various purposes.
|
||||
* There are two sets of completely programmable pins on the Raduino.
|
||||
* First, on the top of the board, in line with the LCD connector is an 8-pin connector
|
||||
* that is largely meant for analog inputs and front-panel control. It has a regulated 5v output,
|
||||
* ground and six pins. Each of these six pins can be individually programmed
|
||||
* either as an analog input, a digital input or a digital output.
|
||||
* The pins are assigned as follows (left to right, display facing you):
|
||||
* Pin 1 (Violet), A7, SPARE
|
||||
* Pin 2 (Blue), A6, KEYER (DATA)
|
||||
* Pin 3 (Green), +5v
|
||||
* Pin 4 (Yellow), Gnd
|
||||
* Pin 5 (Orange), A3, PTT
|
||||
* Pin 6 (Red), A2, F BUTTON
|
||||
* Pin 7 (Brown), A1, ENC B
|
||||
* Pin 8 (Black), A0, ENC A
|
||||
*Note: A5, A4 are wired to the Si5351 as I2C interface
|
||||
* *
|
||||
* Though, this can be assigned anyway, for this application of the Arduino, we will make the following
|
||||
* assignment
|
||||
* A2 will connect to the PTT line, which is the usually a part of the mic connector
|
||||
* A3 is connected to a push button that can momentarily ground this line. This will be used for RIT/Bandswitching, etc.
|
||||
* A6 is to implement a keyer, it is reserved and not yet implemented
|
||||
* A7 is connected to a center pin of good quality 100K or 10K linear potentiometer with the two other ends connected to
|
||||
* ground and +5v lines available on the connector. This implments the tuning mechanism
|
||||
*/
|
||||
#define ENC_A (A0)
|
||||
#define ENC_B (A1)
|
||||
#define FBUTTON (A2)
|
||||
#define PTT (A3)
|
||||
#define ANALOG_KEYER (A6)
|
||||
#define ANALOG_SPARE (A7)
|
||||
#define ANALOG_SMETER (A7) //by KD8CEC
|
||||
|
||||
|
||||
/**
|
||||
* 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) //Relay
|
||||
#define CW_TONE (6)
|
||||
#define TX_LPF_A (5) //Relay
|
||||
#define TX_LPF_B (4) //Relay
|
||||
#define TX_LPF_C (3) //Relay
|
||||
#define CW_KEY (2)
|
||||
|
||||
//==============================================================================
|
||||
// for public, Variable, functions
|
||||
//==============================================================================
|
||||
#define WSPR_BAND_COUNT 3
|
||||
#define TX_SSB 0
|
||||
#define TX_CW 1
|
||||
#define printLineF1(x) (printLineF(1, x))
|
||||
#define printLineF2(x) (printLineF(0, x))
|
||||
|
||||
//0x00 : None, 0x01 : MODE, 0x02:BAND+, 0x03:BAND-, 0x04:TUNE_STEP, 0x05:VFO Toggle, 0x06:SplitOn/Off, 0x07:TX/ON-OFF, 0x08:SDR Mode On / Off, 0x09:Rit Toggle
|
||||
#define FUNCTION_KEY_ADC 80 //MODE, BAND(-), BAND(+), STEP
|
||||
#define FKEY_PRESS 0x78
|
||||
#define FKEY_MODE 0x01
|
||||
#define FKEY_BANDUP 0x02
|
||||
#define FKEY_BANDDOWN 0x03
|
||||
#define FKEY_STEP 0x04
|
||||
#define FKEY_VFOCHANGE 0x05
|
||||
#define FKEY_SPLIT 0x06
|
||||
#define FKEY_TXOFF 0x07
|
||||
#define FKEY_SDRMODE 0x08
|
||||
#define FKEY_RIT 0x09
|
||||
|
||||
#define FKEY_ENTER 0x0A
|
||||
#define FKEY_POINT 0x0B
|
||||
#define FKEY_DELETE 0x0C
|
||||
#define FKEY_CANCEL 0x0D
|
||||
|
||||
#define FKEY_NUM0 0x10
|
||||
#define FKEY_NUM1 0x11
|
||||
#define FKEY_NUM2 0x12
|
||||
#define FKEY_NUM3 0x13
|
||||
#define FKEY_NUM4 0x14
|
||||
#define FKEY_NUM5 0x15
|
||||
#define FKEY_NUM6 0x16
|
||||
#define FKEY_NUM7 0x17
|
||||
#define FKEY_NUM8 0x18
|
||||
#define FKEY_NUM9 0x19
|
||||
|
||||
#define FKEY_TYPE_MAX 0x1F
|
||||
|
||||
extern unsigned long frequency;
|
||||
extern byte WsprMSGCount;
|
||||
extern byte sMeterLevels[9];
|
||||
extern byte KeyValues[16][3]; //Set : Start Value, End Value, Key Type, 16 Set (3 * 16 = 48)
|
||||
|
||||
extern void printLine1(const char *c);
|
||||
extern void printLine2(const char *c);
|
||||
extern void printLineF(char linenmbr, const __FlashStringHelper *c);
|
||||
extern void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetType);
|
||||
extern byte delay_background(unsigned delayTime, byte fromType);
|
||||
extern int btnDown(void);
|
||||
extern char c[30];
|
||||
extern char b[30];
|
||||
extern int enc_read(void);
|
||||
extern 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 char byteToChar(byte srcByte);
|
||||
extern void DisplayCallsign(byte callSignLength);
|
||||
extern void DisplayVersionInfo(const char* fwVersionInfo);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,127 +0,0 @@
|
||||
/*************************************************************************
|
||||
header file for EEProm Address Map by KD8CEC
|
||||
It must be protected to protect the factory calibrated calibration.
|
||||
-----------------------------------------------------------------------------
|
||||
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/>.
|
||||
**************************************************************************/
|
||||
//==============================================================================
|
||||
// Factory-shipped EEProm address
|
||||
// (factory Firmware)
|
||||
// Address : 0 ~ 31
|
||||
//==============================================================================
|
||||
#define MASTER_CAL 0
|
||||
#define LSB_CAL 4
|
||||
#define USB_CAL 8
|
||||
#define SIDE_TONE 12
|
||||
//these are ids of the vfos as well as their offset into the eeprom storage, don't change these 'magic' values
|
||||
#define VFO_A 16
|
||||
#define VFO_B 20
|
||||
#define CW_SIDETONE 24
|
||||
#define CW_SPEED 28
|
||||
|
||||
//==============================================================================
|
||||
// The spare space available in the original firmware #1
|
||||
// Address : 32 ~ 63
|
||||
//==============================================================================
|
||||
#define RESERVE_FOR_FACTORY1 32
|
||||
|
||||
//==============================================================================
|
||||
// The spare space available in the original firmware #2
|
||||
// (Enabled if the EEProm address is insufficient)
|
||||
// Address : 64 ~ 100
|
||||
//==============================================================================
|
||||
#define RESERVE_FOR_FACTORY2 64
|
||||
|
||||
//==============================================================================
|
||||
// KD8CEC EEPROM MAP
|
||||
// Address : 101 ~ 1023
|
||||
// 256 is the base address
|
||||
// 256 ~ 1023 (EEProm Section #1)
|
||||
// 255 ~ 101 (EEProm Section #2)
|
||||
//==============================================================================
|
||||
|
||||
//0x00 : None, 0x01 : MODE, 0x02:BAND+, 0x03:BAND-, 0x04:TUNE_STEP, 0x05:VFO Toggle, 0x06:SplitOn/Off, 0x07:TX/ON-OFF, 0x08:SDR Mode On / Off, 0x09:Rit Toggle
|
||||
#define EXTENDED_KEY_RANGE 140 //Extended Key => Set : Start Value, End Value, Key Type, 16 Set (3 * 16 = 48)
|
||||
|
||||
#define I2C_LCD_MASTER 190
|
||||
#define I2C_LCD_SECOND 191
|
||||
|
||||
#define S_METER_LEVELS 230 //LEVEL0 ~ LEVEL7
|
||||
|
||||
#define ADVANCED_FREQ_OPTION1 240 //Bit0: use IFTune_Value, Bit1 : use Stored enabled SDR Mode, Bit2 : dynamic sdr frequency
|
||||
#define IF1_CAL 241
|
||||
#define ENABLE_SDR 242
|
||||
#define SDR_FREQUNCY 243
|
||||
#define CW_CAL 252
|
||||
|
||||
#define VFO_A_MODE 256
|
||||
#define VFO_B_MODE 257
|
||||
#define CW_DELAY 258
|
||||
#define CW_START 259
|
||||
#define HAM_BAND_COUNT 260 //
|
||||
#define TX_TUNE_TYPE 261 //
|
||||
#define HAM_BAND_RANGE 262 //FROM (2BYTE) TO (2BYTE) * 10 = 40byte
|
||||
#define HAM_BAND_FREQS 302 //40, 1 BAND = 4Byte most bit is mode
|
||||
#define TUNING_STEP 342 //TUNING STEP * 6 (index 1 + STEPS 5) //1STEP :
|
||||
|
||||
//for reduce cw key error, eeprom address
|
||||
#define CW_ADC_MOST_BIT1 348 //most 2bits of DOT_TO , DOT_FROM, ST_TO, ST_FROM
|
||||
#define CW_ADC_ST_FROM 349 //CW ADC Range STRAIGHT KEY from (Lower 8 bit)
|
||||
#define CW_ADC_ST_TO 350 //CW ADC Range STRAIGHT KEY to (Lower 8 bit)
|
||||
#define CW_ADC_DOT_FROM 351 //CW ADC Range DOT from (Lower 8 bit)
|
||||
#define CW_ADC_DOT_TO 352 //CW ADC Range DOT to (Lower 8 bit)
|
||||
|
||||
#define CW_ADC_MOST_BIT2 353 //most 2bits of BOTH_TO, BOTH_FROM, DASH_TO, DASH_FROM
|
||||
#define CW_ADC_DASH_FROM 354 //CW ADC Range DASH from (Lower 8 bit)
|
||||
#define CW_ADC_DASH_TO 355 //CW ADC Range DASH to (Lower 8 bit)
|
||||
#define CW_ADC_BOTH_FROM 356 //CW ADC Range BOTH from (Lower 8 bit)
|
||||
#define CW_ADC_BOTH_TO 357 //CW ADC Range BOTH to (Lower 8 bit)
|
||||
#define CW_KEY_TYPE 358
|
||||
#define CW_DISPLAY_SHIFT 359 //Transmits on CWL, CWU Mode, LCD Frequency shifts Sidetone Frequency.
|
||||
//(7:Enable / Disable //0: enable, 1:disable, (default is applied shift)
|
||||
//6 : 0 : Adjust Pulus, 1 : Adjust Minus
|
||||
//0~5: Adjust Value : * 10 = Adjust Value (0~300)
|
||||
#define COMMON_OPTION0 360 //0: Confirm : CW Frequency Shift
|
||||
//1 : IF Shift Save
|
||||
#define IF_SHIFTVALUE 363
|
||||
|
||||
#define DISPLAY_OPTION1 361 //Display Option1
|
||||
#define DISPLAY_OPTION2 362 //Display Option2
|
||||
|
||||
#define WSPR_COUNT 443 //WSPR_MESSAGE_COUNT
|
||||
#define WSPR_MESSAGE1 444 //
|
||||
#define WSPR_MESSAGE2 490 //
|
||||
#define WSPR_MESSAGE3 536 //
|
||||
#define WSPR_MESSAGE4 582 //
|
||||
|
||||
#define CHANNEL_FREQ 630 //Channel 1 ~ 20, 1 Channel = 4 bytes
|
||||
#define CHANNEL_DESC 710 //Channel 1 ~ 20, 1 Channel = 4 bytes
|
||||
#define RESERVE3 770 //Reserve3 between Channel and Firmware id check
|
||||
|
||||
//Check Firmware type and version
|
||||
#define FIRMWAR_ID_ADDR 776 //776 : 0x59, 777 :0x58, 778 : 0x68 : Id Number, if not found id, erase eeprom(32~1023) for prevent system error.
|
||||
#define VERSION_ADDRESS 779 //check Firmware version
|
||||
//USER INFORMATION
|
||||
#define USER_CALLSIGN_KEY 780 //0x59
|
||||
#define USER_CALLSIGN_LEN 781 //1BYTE (OPTION + LENGTH) + CALLSIGN (MAXIMUM 18)
|
||||
#define USER_CALLSIGN_DAT 782 //CALL SIGN DATA //direct EEPROM to LCD basic offset
|
||||
|
||||
//AUTO KEY STRUCTURE
|
||||
//AUTO KEY USE 800 ~ 1023
|
||||
#define CW_AUTO_MAGIC_KEY 800 //0x73
|
||||
#define CW_AUTO_COUNT 801 //0 ~ 255
|
||||
#define CW_AUTO_DATA 803 //[INDEX, INDEX, INDEX,DATA,DATA, DATA (Positon offset is CW_AUTO_DATA
|
||||
#define CW_DATA_OFSTADJ CW_AUTO_DATA - USER_CALLSIGN_DAT //offset adjust for ditect eeprom to lcd (basic offset is USER_CALLSIGN_DAT
|
||||
#define CW_STATION_LEN 1023 //value range : 4 ~ 30
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
|
||||
/**
|
||||
* This procedure is only for those who have a signal generator/transceiver tuned to exactly 7.150 and a dummy load
|
||||
*/
|
||||
|
||||
void btnWaitForClick(){
|
||||
while(!btnDown())
|
||||
delay(50);
|
||||
while(btnDown())
|
||||
delay(50);
|
||||
delay(50);
|
||||
}
|
||||
|
||||
void factory_alignment(){
|
||||
|
||||
factoryCalibration(1);
|
||||
line2DisplayStatus = 1;
|
||||
|
||||
if (calibration == 0){
|
||||
printLine2("Setup Aborted");
|
||||
return;
|
||||
}
|
||||
|
||||
//move it away to 7.160 for an LSB signal
|
||||
setFrequency(7160000l);
|
||||
updateDisplay();
|
||||
printLine2("#2 BFO");
|
||||
delay(1000);
|
||||
|
||||
usbCarrier = 11994999l;
|
||||
menuSetupCarrier(1);
|
||||
|
||||
if (usbCarrier == 11994999l){
|
||||
printLine2("Setup Aborted");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
printLine2("#3:Test 3.5MHz");
|
||||
cwMode = 0;
|
||||
isUSB = false;
|
||||
setFrequency(3500000l);
|
||||
updateDisplay();
|
||||
|
||||
while (!btnDown()){
|
||||
checkPTT();
|
||||
delay(100);
|
||||
}
|
||||
|
||||
btnWaitForClick();
|
||||
printLine2("#4:Test 7MHz");
|
||||
|
||||
setFrequency(7150000l);
|
||||
updateDisplay();
|
||||
while (!btnDown()){
|
||||
checkPTT();
|
||||
delay(100);
|
||||
}
|
||||
|
||||
btnWaitForClick();
|
||||
printLine2("#5:Test 14MHz");
|
||||
|
||||
cwMode = 0;
|
||||
isUSB = true;
|
||||
setFrequency(14000000l);
|
||||
updateDisplay();
|
||||
while (!btnDown()){
|
||||
checkPTT();
|
||||
delay(100);
|
||||
}
|
||||
|
||||
btnWaitForClick();
|
||||
printLine2("#6:Test 28MHz");
|
||||
|
||||
setFrequency(28000000l);
|
||||
updateDisplay();
|
||||
while (!btnDown()){
|
||||
checkPTT();
|
||||
delay(100);
|
||||
}
|
||||
|
||||
printLine2("Alignment done");
|
||||
delay(1000);
|
||||
|
||||
cwMode = 0;
|
||||
isUSB = false;
|
||||
setFrequency(7150000l);
|
||||
updateDisplay();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,369 +0,0 @@
|
||||
/**
|
||||
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.
|
||||
* They all use just one analog input line. This is how it works.
|
||||
* The analog line has the internal pull-up resistor enabled.
|
||||
* When a straight key is connected, it shorts the pull-up resistor, analog input is 0 volts
|
||||
* When a paddle is connected, the dot and the dash are connected to the analog pin through
|
||||
* a 10K and a 2.2K resistors. These produce a 4v and a 2v input to the analog pins.
|
||||
* So, the readings are as follows :
|
||||
* 0v - straight key
|
||||
* 1-2.5 v - paddle dot
|
||||
* 2.5 to 4.5 v - paddle dash
|
||||
* 2.0 to 0.5 v - dot and dash pressed
|
||||
*
|
||||
* The keyer is written to transparently handle all these cases
|
||||
*
|
||||
* Generating CW
|
||||
* The CW is cleanly generated by unbalancing the front-end mixer
|
||||
* and putting the local oscillator directly at the CW transmit frequency.
|
||||
* The sidetone, generated by the Arduino is injected into the volume control
|
||||
*/
|
||||
|
||||
|
||||
// in milliseconds, this is the parameter that determines how long the tx will hold between cw key downs
|
||||
//#define CW_TIMEOUT (600l) //Change to CW Delaytime for value save to eeprom
|
||||
#define PADDLE_DOT 1
|
||||
#define PADDLE_DASH 2
|
||||
#define PADDLE_BOTH 3
|
||||
#define PADDLE_STRAIGHT 4
|
||||
|
||||
//we store the last padde's character
|
||||
//to alternatively send dots and dashes
|
||||
//when both are simultaneously pressed
|
||||
char lastPaddle = 0;
|
||||
|
||||
//reads the analog keyer pin and reports the paddle
|
||||
byte getPaddle(){
|
||||
int paddle = analogRead(ANALOG_KEYER);
|
||||
|
||||
if (paddle > 800) // above 4v is up
|
||||
return 0;
|
||||
|
||||
if (paddle > 600) // 4-3v is dot
|
||||
return PADDLE_DASH;
|
||||
else if (paddle > 300) //1-2v is dash
|
||||
return PADDLE_DOT;
|
||||
else if (paddle > 50)
|
||||
return PADDLE_BOTH; //both are between 1 and 2v
|
||||
else
|
||||
return PADDLE_STRAIGHT; //less than 1v is the straight key
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts transmitting the carrier with the sidetone
|
||||
* It assumes that we have called cwTxStart and not called cwTxStop
|
||||
* each time it is called, the cwTimeOut is pushed further into the future
|
||||
*/
|
||||
void cwKeydown(){
|
||||
keyDown = 1; //tracks the CW_KEY
|
||||
tone(CW_TONE, (int)sideTone);
|
||||
digitalWrite(CW_KEY, 1);
|
||||
|
||||
//Modified by KD8CEC, for CW Delay Time save to eeprom
|
||||
//cwTimeout = millis() + CW_TIMEOUT;
|
||||
cwTimeout = millis() + cwDelayTime * 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the cw carrier transmission along with the sidetone
|
||||
* Pushes the cwTimeout further into the future
|
||||
*/
|
||||
void cwKeyUp(){
|
||||
keyDown = 0; //tracks the CW_KEY
|
||||
noTone(CW_TONE);
|
||||
digitalWrite(CW_KEY, 0);
|
||||
|
||||
//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
|
||||
* 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
|
||||
* Each time the key is hit the cwTimeout is pushed to a time in the future by cwKeyDown()
|
||||
*/
|
||||
/*
|
||||
void cwKeyer(){
|
||||
byte paddle;
|
||||
lastPaddle = 0;
|
||||
|
||||
while(1){
|
||||
paddle = getPaddle();
|
||||
|
||||
// do nothing if the paddle has not been touched, unless
|
||||
// we are in the cw mode and we have timed out
|
||||
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()){
|
||||
cwTimeout = 0;
|
||||
keyDown = 0;
|
||||
stopTx();
|
||||
}
|
||||
|
||||
if (!cwTimeout)
|
||||
return;
|
||||
|
||||
Check_Cat(2); //for uBITX on Raspberry pi, when straight keying, disconnect / test complete
|
||||
continue;
|
||||
}
|
||||
|
||||
//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 (!inTx){
|
||||
keyDown = 0;
|
||||
//Modified by KD8CEC, for CW Delay Time save to eeprom
|
||||
//cwTimeout = millis() + CW_TIMEOUT;
|
||||
cwTimeout = millis() + cwDelayTime * 10;
|
||||
|
||||
startTx(TX_CW, 0); //disable updateDisplay Command for reduce latency time
|
||||
updateDisplay();
|
||||
|
||||
//DelayTime Option
|
||||
delay_background(delayBeforeCWStartTime * 2, 2);
|
||||
}
|
||||
|
||||
// star the transmission)
|
||||
// we store the transmitted character in the lastPaddle
|
||||
cwKeydown();
|
||||
if (paddle == PADDLE_DOT){
|
||||
//delay(cwSpeed);
|
||||
delay_background(cwSpeed, 3);
|
||||
lastPaddle = PADDLE_DOT;
|
||||
}
|
||||
else if (paddle == PADDLE_DASH){
|
||||
//delay(cwSpeed * 3);
|
||||
delay_background(cwSpeed * 3, 3);
|
||||
lastPaddle = PADDLE_DASH;
|
||||
}
|
||||
else if (paddle == PADDLE_BOTH){ //both paddles down
|
||||
//depending upon what was sent last, send the other
|
||||
if (lastPaddle == PADDLE_DOT) {
|
||||
//delay(cwSpeed * 3);
|
||||
delay_background(cwSpeed * 3, 3);
|
||||
lastPaddle = PADDLE_DASH;
|
||||
}else{
|
||||
//delay(cwSpeed);
|
||||
delay_background(cwSpeed, 3);
|
||||
lastPaddle = PADDLE_DOT;
|
||||
}
|
||||
}
|
||||
else if (paddle == PADDLE_STRAIGHT){
|
||||
while (getPaddle() == PADDLE_STRAIGHT) {
|
||||
delay(1);
|
||||
Check_Cat(2);
|
||||
}
|
||||
lastPaddle = PADDLE_STRAIGHT;
|
||||
}
|
||||
cwKeyUp();
|
||||
//introduce a dot long gap between characters if the keyer was used
|
||||
if (lastPaddle != PADDLE_STRAIGHT)
|
||||
delay(cwSpeed);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,840 +0,0 @@
|
||||
/*************************************************************************
|
||||
KD8CEC's uBITX Display Routine for LCD1602 Parrel
|
||||
1.This is the display code for the default LCD mounted in uBITX.
|
||||
2.Display related functions of uBITX. Some functions moved from uBITX_Ui.
|
||||
3.uBITX Idle time Processing
|
||||
Functions that run at times that do not affect TX, CW, and CAT
|
||||
It is called in 1/10 time unit.
|
||||
-----------------------------------------------------------------------------
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
#include "ubitx.h"
|
||||
|
||||
//Common Defines *********************************************************
|
||||
#define LCD_CLEARDISPLAY 0x01
|
||||
#define LCD_RETURNHOME 0x02
|
||||
#define LCD_ENTRYMODESET 0x04
|
||||
#define LCD_DISPLAYCONTROL 0x08
|
||||
#define LCD_CURSORSHIFT 0x10
|
||||
#define LCD_FUNCTIONSET 0x20
|
||||
#define LCD_SETCGRAMADDR 0x40
|
||||
#define LCD_SETDDRAMADDR 0x80
|
||||
|
||||
// flags for display entry mode
|
||||
#define LCD_ENTRYRIGHT 0x00
|
||||
#define LCD_ENTRYLEFT 0x02
|
||||
#define LCD_ENTRYSHIFTINCREMENT 0x01
|
||||
#define LCD_ENTRYSHIFTDECREMENT 0x00
|
||||
|
||||
// flags for display on/off control
|
||||
#define LCD_DISPLAYON 0x04
|
||||
#define LCD_DISPLAYOFF 0x00
|
||||
#define LCD_CURSORON 0x02
|
||||
#define LCD_CURSOROFF 0x00
|
||||
#define LCD_BLINKON 0x01
|
||||
#define LCD_BLINKOFF 0x00
|
||||
|
||||
// flags for display/cursor shift
|
||||
#define LCD_DISPLAYMOVE 0x08
|
||||
#define LCD_CURSORMOVE 0x00
|
||||
#define LCD_MOVERIGHT 0x04
|
||||
#define LCD_MOVELEFT 0x00
|
||||
|
||||
// flags for function set
|
||||
#define LCD_8BITMODE 0x10
|
||||
#define LCD_4BITMODE 0x00
|
||||
#define LCD_2LINE 0x08
|
||||
#define LCD_1LINE 0x00
|
||||
#define LCD_5x10DOTS 0x04
|
||||
#define LCD_5x8DOTS 0x00
|
||||
|
||||
// flags for backlight control
|
||||
#define LCD_BACKLIGHT 0x08
|
||||
#define LCD_NOBACKLIGHT 0x00
|
||||
|
||||
//========================================================================
|
||||
//Begin of TinyLCD Library by KD8CEC
|
||||
//========================================================================
|
||||
|
||||
#ifdef UBITX_DISPLAY_LCD1602P
|
||||
/*************************************************************************
|
||||
LCD1602_TINY Library for 16 x 2 LCD
|
||||
Referecnce Source : LiquidCrystal.cpp
|
||||
KD8CEC
|
||||
|
||||
This source code is modified version for small program memory
|
||||
from Arduino LiquidCrystal Library
|
||||
|
||||
I wrote this code myself, so there is no license restriction.
|
||||
So this code allows anyone to write with confidence.
|
||||
But keep it as long as the original author of the code.
|
||||
DE Ian KD8CEC
|
||||
**************************************************************************/
|
||||
|
||||
#define LCD_Command(x) (LCD_Send(x, LOW))
|
||||
#define LCD_Write(x) (LCD_Send(x, HIGH))
|
||||
|
||||
#define UBITX_DISPLAY_LCD1602_BASE
|
||||
|
||||
//Define connected PIN
|
||||
#define LCD_PIN_RS 8
|
||||
#define LCD_PIN_EN 9
|
||||
uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13};
|
||||
|
||||
void write4bits(uint8_t value)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
digitalWrite(LCD_PIN_DAT[i], (value >> i) & 0x01);
|
||||
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(LCD_PIN_EN, HIGH);
|
||||
delayMicroseconds(1); // enable pulse must be >450ns
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
delayMicroseconds(100); // commands need > 37us to settle
|
||||
}
|
||||
|
||||
void LCD_Send(uint8_t value, uint8_t mode)
|
||||
{
|
||||
digitalWrite(LCD_PIN_RS, mode);
|
||||
write4bits(value>>4);
|
||||
write4bits(value);
|
||||
}
|
||||
|
||||
void LCD1602_Init()
|
||||
{
|
||||
pinMode(LCD_PIN_RS, OUTPUT);
|
||||
pinMode(LCD_PIN_EN, OUTPUT);
|
||||
for (int i = 0; i < 4; i++)
|
||||
pinMode(LCD_PIN_DAT[i], OUTPUT);
|
||||
|
||||
delayMicroseconds(50);
|
||||
|
||||
// Now we pull both RS and R/W low to begin commands
|
||||
digitalWrite(LCD_PIN_RS, LOW);
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
|
||||
// we start in 8bit mode, try to set 4 bit mode
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// second try
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// third go!
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(150);
|
||||
|
||||
// finally, set to 4-bit interface
|
||||
write4bits(0x02);
|
||||
|
||||
// finally, set # lines, font size, etc.
|
||||
LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE);
|
||||
|
||||
// turn the display on with no cursor or blinking default
|
||||
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
|
||||
|
||||
// clear it off
|
||||
LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||
delayMicroseconds(2000); // this command takes a long time!
|
||||
|
||||
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
|
||||
}
|
||||
|
||||
#endif
|
||||
//========================================================================
|
||||
//End of TinyLCD Library by KD8CEC
|
||||
//========================================================================
|
||||
|
||||
|
||||
//========================================================================
|
||||
//Begin of I2CTinyLCD Library by KD8CEC
|
||||
//========================================================================
|
||||
#ifdef UBITX_DISPLAY_LCD1602I
|
||||
#include <Wire.h>
|
||||
/*************************************************************************
|
||||
I2C Tiny LCD Library
|
||||
Referecnce Source : LiquidCrystal_I2C.cpp // Based on the work by DFRobot
|
||||
KD8CEC
|
||||
|
||||
This source code is modified version for small program memory
|
||||
from Arduino LiquidCrystal_I2C Library
|
||||
|
||||
I wrote this code myself, so there is no license restriction.
|
||||
So this code allows anyone to write with confidence.
|
||||
But keep it as long as the original author of the code.
|
||||
Ian KD8CEC
|
||||
**************************************************************************/
|
||||
#define UBITX_DISPLAY_LCD1602_BASE
|
||||
|
||||
#define En B00000100 // Enable bit
|
||||
#define Rw B00000010 // Read/Write bit
|
||||
#define Rs B00000001 // Register select bit
|
||||
|
||||
#define LCD_Command(x) (LCD_Send(x, 0))
|
||||
#define LCD_Write(x) (LCD_Send(x, Rs))
|
||||
|
||||
uint8_t _Addr;
|
||||
uint8_t _displayfunction;
|
||||
uint8_t _displaycontrol;
|
||||
uint8_t _displaymode;
|
||||
uint8_t _numlines;
|
||||
uint8_t _cols;
|
||||
uint8_t _rows;
|
||||
uint8_t _backlightval;
|
||||
|
||||
#define printIIC(args) Wire.write(args)
|
||||
|
||||
void expanderWrite(uint8_t _data)
|
||||
{
|
||||
Wire.beginTransmission(_Addr);
|
||||
printIIC((int)(_data) | _backlightval);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void pulseEnable(uint8_t _data){
|
||||
expanderWrite(_data | En); // En high
|
||||
delayMicroseconds(1); // enable pulse must be >450ns
|
||||
|
||||
expanderWrite(_data & ~En); // En low
|
||||
delayMicroseconds(50); // commands need > 37us to settle
|
||||
}
|
||||
|
||||
void write4bits(uint8_t value)
|
||||
{
|
||||
expanderWrite(value);
|
||||
pulseEnable(value);
|
||||
}
|
||||
|
||||
void LCD_Send(uint8_t value, uint8_t mode)
|
||||
{
|
||||
uint8_t highnib=value&0xf0;
|
||||
uint8_t lownib=(value<<4)&0xf0;
|
||||
write4bits((highnib)|mode);
|
||||
write4bits((lownib)|mode);
|
||||
}
|
||||
|
||||
|
||||
// Turn the (optional) backlight off/on
|
||||
void noBacklight(void) {
|
||||
_backlightval=LCD_NOBACKLIGHT;
|
||||
expanderWrite(0);
|
||||
}
|
||||
|
||||
void backlight(void) {
|
||||
_backlightval=LCD_BACKLIGHT;
|
||||
expanderWrite(0);
|
||||
}
|
||||
|
||||
void LCD1602_Init()
|
||||
{
|
||||
//I2C Init
|
||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
||||
_cols = 16;
|
||||
_rows = 2;
|
||||
_backlightval = LCD_NOBACKLIGHT;
|
||||
Wire.begin();
|
||||
|
||||
delay(50);
|
||||
|
||||
// Now we pull both RS and R/W low to begin commands
|
||||
expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
|
||||
delay(1000);
|
||||
//put the LCD into 4 bit mode
|
||||
// this is according to the hitachi HD44780 datasheet
|
||||
// figure 24, pg 46
|
||||
|
||||
// we start in 8bit mode, try to set 4 bit mode
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// second try
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// third go!
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(150);
|
||||
|
||||
// finally, set to 4-bit interface
|
||||
write4bits(0x02 << 4);
|
||||
|
||||
// finally, set # lines, font size, etc.
|
||||
LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE);
|
||||
|
||||
// turn the display on with no cursor or blinking default
|
||||
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
|
||||
|
||||
// clear it off
|
||||
LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||
//delayMicroseconds(2000); // this command takes a long time!
|
||||
delayMicroseconds(1000); // this command takes a long time!
|
||||
|
||||
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
|
||||
|
||||
backlight();
|
||||
}
|
||||
|
||||
/*
|
||||
void LCD_Print(const char *c)
|
||||
{
|
||||
for (uint8_t i = 0; i < strlen(c); i++)
|
||||
{
|
||||
if (*(c + i) == 0x00) return;
|
||||
LCD_Write(*(c + i));
|
||||
}
|
||||
}
|
||||
|
||||
void LCD_SetCursor(uint8_t col, uint8_t row)
|
||||
{
|
||||
LCD_Command(LCD_SETDDRAMADDR | (col + row * 0x40)); //0 : 0x00, 1 : 0x40, only for 16 x 2 lcd
|
||||
}
|
||||
|
||||
void LCD_CreateChar(uint8_t location, uint8_t charmap[])
|
||||
{
|
||||
location &= 0x7; // we only have 8 locations 0-7
|
||||
LCD_Command(LCD_SETCGRAMADDR | (location << 3));
|
||||
for (int i=0; i<8; i++)
|
||||
LCD_Write(charmap[i]);
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
//========================================================================
|
||||
//End of I2CTinyLCD Library by KD8CEC
|
||||
//========================================================================
|
||||
|
||||
|
||||
//========================================================================
|
||||
// 16 X 02 LCD Routines
|
||||
//Begin of Display Base Routines (Init, printLine..)
|
||||
//========================================================================
|
||||
#ifdef UBITX_DISPLAY_LCD1602_BASE
|
||||
|
||||
//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA
|
||||
#define OPTION_SKINNYBARS
|
||||
|
||||
char c[30], b[30];
|
||||
char printBuff[2][17]; //mirrors what is showing on the two lines of the display
|
||||
|
||||
|
||||
void LCD_Print(const char *c)
|
||||
{
|
||||
for (uint8_t i = 0; i < strlen(c); i++)
|
||||
{
|
||||
if (*(c + i) == 0x00) return;
|
||||
LCD_Write(*(c + i));
|
||||
}
|
||||
}
|
||||
|
||||
void LCD_SetCursor(uint8_t col, uint8_t row)
|
||||
{
|
||||
LCD_Command(LCD_SETDDRAMADDR | (col + row * 0x40)); //0 : 0x00, 1 : 0x40, only for 16 x 2 lcd
|
||||
}
|
||||
|
||||
void LCD_CreateChar(uint8_t location, uint8_t charmap[])
|
||||
{
|
||||
location &= 0x7; // we only have 8 locations 0-7
|
||||
LCD_Command(LCD_SETCGRAMADDR | (location << 3));
|
||||
for (int i=0; i<8; i++)
|
||||
LCD_Write(charmap[i]);
|
||||
}
|
||||
|
||||
void LCD_Init(void)
|
||||
{
|
||||
LCD1602_Init();
|
||||
initMeter(); //for Meter Display
|
||||
}
|
||||
|
||||
// The generic routine to display one line on the LCD
|
||||
void printLine(unsigned char linenmbr, const char *c) {
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||
if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change
|
||||
LCD_SetCursor(0, linenmbr); // place the cursor at the beginning of the selected line
|
||||
LCD_Print(c);
|
||||
strcpy(printBuff[linenmbr], c);
|
||||
|
||||
for (byte i = strlen(c); i < 16; i++) { // add white spaces until the end of the 16 characters line is reached
|
||||
LCD_Write(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printLineF(char linenmbr, const __FlashStringHelper *c)
|
||||
{
|
||||
int i;
|
||||
char tmpBuff[17];
|
||||
PGM_P p = reinterpret_cast<PGM_P>(c);
|
||||
|
||||
for (i = 0; i < 17; i++){
|
||||
unsigned char fChar = pgm_read_byte(p++);
|
||||
tmpBuff[i] = fChar;
|
||||
if (fChar == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
printLine(linenmbr, tmpBuff);
|
||||
}
|
||||
|
||||
#define LCD_MAX_COLUMN 16
|
||||
void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) {
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||
|
||||
LCD_SetCursor(lcdColumn, linenmbr);
|
||||
|
||||
for (byte i = eepromStartIndex; i <= eepromEndIndex; i++)
|
||||
{
|
||||
if (++lcdColumn <= LCD_MAX_COLUMN)
|
||||
LCD_Write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (byte i = lcdColumn; i < 16; i++) //Right Padding by Space
|
||||
LCD_Write(' ');
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1(const char *c)
|
||||
{
|
||||
printLine(1,c);
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2(const char *c)
|
||||
{
|
||||
printLine(0,c);
|
||||
}
|
||||
|
||||
void clearLine2()
|
||||
{
|
||||
printLine2("");
|
||||
line2DisplayStatus = 0;
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1Clear(){
|
||||
printLine(1,"");
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2Clear(){
|
||||
printLine(0, "");
|
||||
}
|
||||
|
||||
void printLine2ClearAndUpdate(){
|
||||
printLine(0, "");
|
||||
line2DisplayStatus = 0;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
//==================================================================================
|
||||
//End of Display Base Routines
|
||||
//==================================================================================
|
||||
|
||||
|
||||
//==================================================================================
|
||||
//Begin of User Interface Routines
|
||||
//==================================================================================
|
||||
|
||||
//Main Display
|
||||
// this builds up the top line of the display with frequency and mode
|
||||
void updateDisplay() {
|
||||
// tks Jack Purdum W8TEE
|
||||
// replaced fsprint commmands by str commands for code size reduction
|
||||
// replace code for Frequency numbering error (alignment, point...) by KD8CEC
|
||||
int i;
|
||||
unsigned long tmpFreq = frequency; //
|
||||
|
||||
memset(c, 0, sizeof(c));
|
||||
|
||||
if (inTx){
|
||||
if (isCWAutoMode == 2) {
|
||||
for (i = 0; i < 4; i++)
|
||||
c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' ');
|
||||
|
||||
//display Sending Index
|
||||
c[4] = byteToChar(sendingCWTextIndex);
|
||||
c[5] = '=';
|
||||
}
|
||||
else {
|
||||
if (cwTimeout > 0)
|
||||
strcpy(c, " CW:");
|
||||
else
|
||||
strcpy(c, " TX:");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ritOn)
|
||||
strcpy(c, "RIT ");
|
||||
else {
|
||||
if (cwMode == 0)
|
||||
{
|
||||
if (isUSB)
|
||||
strcpy(c, "USB ");
|
||||
else
|
||||
strcpy(c, "LSB ");
|
||||
}
|
||||
else if (cwMode == 1)
|
||||
{
|
||||
strcpy(c, "CWL ");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(c, "CWU ");
|
||||
}
|
||||
}
|
||||
if (vfoActive == VFO_A) // VFO A is active
|
||||
strcat(c, "A:");
|
||||
else
|
||||
strcat(c, "B:");
|
||||
}
|
||||
|
||||
//Fixed by Mitani Massaru (JE4SMQ)
|
||||
if (isShiftDisplayCWFreq == 1)
|
||||
{
|
||||
if (cwMode == 1) //CWL
|
||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
||||
else if (cwMode == 2) //CWU
|
||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
||||
}
|
||||
|
||||
//display frequency
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) c[i] = '.';
|
||||
else {
|
||||
c[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
c[i] = ' ';
|
||||
}
|
||||
|
||||
//remarked by KD8CEC
|
||||
//already RX/TX status display, and over index (16 x 2 LCD)
|
||||
//if (inTx)
|
||||
// strcat(c, " TX");
|
||||
printLine(1, c);
|
||||
|
||||
byte diplayVFOLine = 1;
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayVFOLine = 0;
|
||||
|
||||
if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) ||
|
||||
(vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) {
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write((uint8_t)0);
|
||||
}
|
||||
else if (isCWAutoMode == 2){
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write(0x7E);
|
||||
}
|
||||
else
|
||||
{
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write(':');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char line2Buffer[17];
|
||||
//KD8CEC 200Hz ST
|
||||
//L14.150 200Hz ST
|
||||
//U14.150 +150khz
|
||||
int freqScrollPosition = 0;
|
||||
|
||||
//Example Line2 Optinal Display
|
||||
//immediate execution, not call by scheulder
|
||||
//warning : unused parameter 'displayType' <-- ignore, this is reserve
|
||||
void updateLine2Buffer(char displayType)
|
||||
{
|
||||
unsigned long tmpFreq = 0;
|
||||
if (ritOn)
|
||||
{
|
||||
strcpy(line2Buffer, "RitTX:");
|
||||
|
||||
//display frequency
|
||||
tmpFreq = ritTxFrequency;
|
||||
|
||||
//Fixed by Mitani Massaru (JE4SMQ)
|
||||
if (isShiftDisplayCWFreq == 1)
|
||||
{
|
||||
if (cwMode == 1) //CWL
|
||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
||||
else if (cwMode == 2) //CWU
|
||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
||||
}
|
||||
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
return;
|
||||
} //end of ritOn display
|
||||
|
||||
//other VFO display
|
||||
if (vfoActive == VFO_B)
|
||||
{
|
||||
tmpFreq = vfoA;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpFreq = vfoB;
|
||||
}
|
||||
|
||||
// EXAMPLE 1 & 2
|
||||
//U14.150.100
|
||||
//display frequency
|
||||
for (int i = 9; i >= 0; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 2 || i == 6) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
//EXAMPLE #1
|
||||
if ((displayOption1 & 0x04) == 0x00) //none scroll display
|
||||
line2Buffer[6] = 'M';
|
||||
else
|
||||
{
|
||||
//example #2
|
||||
if (freqScrollPosition++ > 18) //none scroll display time
|
||||
{
|
||||
line2Buffer[6] = 'M';
|
||||
if (freqScrollPosition > 25)
|
||||
freqScrollPosition = -1;
|
||||
}
|
||||
else //scroll frequency
|
||||
{
|
||||
line2Buffer[10] = 'H';
|
||||
line2Buffer[11] = 'z';
|
||||
|
||||
if (freqScrollPosition < 7)
|
||||
{
|
||||
for (int i = 11; i >= 0; i--)
|
||||
if (i - (7 - freqScrollPosition) >= 0)
|
||||
line2Buffer[i] = line2Buffer[i - (7 - freqScrollPosition)];
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 11; i++)
|
||||
if (i + (freqScrollPosition - 7) <= 11)
|
||||
line2Buffer[i] = line2Buffer[i + (freqScrollPosition - 7)];
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
}
|
||||
} //scroll
|
||||
|
||||
line2Buffer[7] = ' ';
|
||||
|
||||
if (isIFShift)
|
||||
{
|
||||
// if (isDirectCall == 1)
|
||||
// for (int i = 0; i < 16; i++)
|
||||
// line2Buffer[i] = ' ';
|
||||
|
||||
//IFShift Offset Value
|
||||
line2Buffer[8] = 'I';
|
||||
line2Buffer[9] = 'F';
|
||||
|
||||
line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0;
|
||||
line2Buffer[11] = 0;
|
||||
line2Buffer[12] = ' ';
|
||||
|
||||
//11, 12, 13, 14, 15
|
||||
memset(b, 0, sizeof(b));
|
||||
ltoa(ifShiftValue, b, DEC);
|
||||
strncat(line2Buffer, b, 5);
|
||||
|
||||
//if (isDirectCall == 1) //if call by encoder (not scheduler), immediate print value
|
||||
printLine2(line2Buffer);
|
||||
} // end of display IF
|
||||
else // step & Key Type display
|
||||
{
|
||||
//if (isDirectCall != 0)
|
||||
// return;
|
||||
|
||||
memset(&line2Buffer[8], ' ', 8);
|
||||
//Step
|
||||
long tmpStep = arTuneStep[tuneStepIndex -1];
|
||||
|
||||
byte isStepKhz = 0;
|
||||
if (tmpStep >= 1000)
|
||||
{
|
||||
isStepKhz = 2;
|
||||
}
|
||||
|
||||
for (int i = 10; i >= 8 - isStepKhz; i--) {
|
||||
if (tmpStep > 0) {
|
||||
line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30;
|
||||
tmpStep /= 10;
|
||||
}
|
||||
else
|
||||
line2Buffer[i +isStepKhz] = ' ';
|
||||
}
|
||||
|
||||
if (isStepKhz == 0)
|
||||
{
|
||||
line2Buffer[11] = 'H';
|
||||
line2Buffer[12] = 'z';
|
||||
}
|
||||
|
||||
line2Buffer[13] = ' ';
|
||||
|
||||
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
||||
if (sdrModeOn == 1)
|
||||
{
|
||||
line2Buffer[13] = 'S';
|
||||
line2Buffer[14] = 'D';
|
||||
line2Buffer[15] = 'R';
|
||||
}
|
||||
else 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);
|
||||
int lineNumber = 0;
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
lineNumber = 1;
|
||||
|
||||
LCD_SetCursor(drawPosition, lineNumber);
|
||||
|
||||
//for (int i = 0; i <26; i++) //meter 5 + +db 1 = 6
|
||||
LCD_Write(lcdMeter[0]);
|
||||
LCD_Write(lcdMeter[1]);
|
||||
}
|
||||
}
|
||||
|
||||
byte testValue = 0;
|
||||
char checkCount = 0;
|
||||
char checkCountSMeter = 0;
|
||||
|
||||
int currentSMeter = 0;
|
||||
byte scaledSMeter = 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;
|
||||
*/
|
||||
|
||||
//S-Meter Display
|
||||
if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency))
|
||||
{
|
||||
int newSMeter;
|
||||
|
||||
//VK2ETA S-Meter from MAX9814 TC pin / divide 4 by KD8CEC for reduce EEPromSize
|
||||
newSMeter = analogRead(ANALOG_SMETER);
|
||||
|
||||
//Faster attack, Slower release
|
||||
currentSMeter = (newSMeter > currentSMeter ? ((currentSMeter * 3 + newSMeter * 7) + 5) / 10 : ((currentSMeter * 7 + newSMeter * 3) + 5) / 10) / 4;
|
||||
|
||||
scaledSMeter = 0;
|
||||
for (byte s = 8; s >= 1; s--) {
|
||||
if (currentSMeter > sMeterLevels[s]) {
|
||||
scaledSMeter = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DisplayMeter(0, scaledSMeter, 14);
|
||||
checkCountSMeter = 0; //Reset Latency time
|
||||
} //end of S-Meter
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//AutoKey LCD Display Routine
|
||||
void Display_AutoKeyTextIndex(byte textIndex)
|
||||
{
|
||||
byte diplayAutoCWLine = 0;
|
||||
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayAutoCWLine = 1;
|
||||
LCD_SetCursor(0, diplayAutoCWLine);
|
||||
LCD_Write(byteToChar(textIndex));
|
||||
LCD_Write(':');
|
||||
}
|
||||
|
||||
void DisplayCallsign(byte callSignLength)
|
||||
{
|
||||
printLineFromEEPRom(0, 0, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT)
|
||||
//delay(500);
|
||||
}
|
||||
|
||||
void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo)
|
||||
{
|
||||
printLineF(1, fwVersionInfo);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,771 +0,0 @@
|
||||
/*************************************************************************
|
||||
KD8CEC's uBITX Display Routine for LCD1602 Dual LCD by KD8CEC
|
||||
1.This is the display code for the default LCD mounted in uBITX.
|
||||
2.Display related functions of uBITX. Some functions moved from uBITX_Ui.
|
||||
3.uBITX Idle time Processing
|
||||
Functions that run at times that do not affect TX, CW, and CAT
|
||||
It is called in 1/10 time unit.
|
||||
-----------------------------------------------------------------------------
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
#include "ubitx.h"
|
||||
|
||||
//Common Defines *********************************************************
|
||||
#define LCD_CLEARDISPLAY 0x01
|
||||
#define LCD_RETURNHOME 0x02
|
||||
#define LCD_ENTRYMODESET 0x04
|
||||
#define LCD_DISPLAYCONTROL 0x08
|
||||
#define LCD_CURSORSHIFT 0x10
|
||||
#define LCD_FUNCTIONSET 0x20
|
||||
#define LCD_SETCGRAMADDR 0x40
|
||||
#define LCD_SETDDRAMADDR 0x80
|
||||
|
||||
// flags for display entry mode
|
||||
#define LCD_ENTRYRIGHT 0x00
|
||||
#define LCD_ENTRYLEFT 0x02
|
||||
#define LCD_ENTRYSHIFTINCREMENT 0x01
|
||||
#define LCD_ENTRYSHIFTDECREMENT 0x00
|
||||
|
||||
// flags for display on/off control
|
||||
#define LCD_DISPLAYON 0x04
|
||||
#define LCD_DISPLAYOFF 0x00
|
||||
#define LCD_CURSORON 0x02
|
||||
#define LCD_CURSOROFF 0x00
|
||||
#define LCD_BLINKON 0x01
|
||||
#define LCD_BLINKOFF 0x00
|
||||
|
||||
// flags for display/cursor shift
|
||||
#define LCD_DISPLAYMOVE 0x08
|
||||
#define LCD_CURSORMOVE 0x00
|
||||
#define LCD_MOVERIGHT 0x04
|
||||
#define LCD_MOVELEFT 0x00
|
||||
|
||||
// flags for function set
|
||||
#define LCD_8BITMODE 0x10
|
||||
#define LCD_4BITMODE 0x00
|
||||
#define LCD_2LINE 0x08
|
||||
#define LCD_1LINE 0x00
|
||||
#define LCD_5x10DOTS 0x04
|
||||
#define LCD_5x8DOTS 0x00
|
||||
|
||||
// flags for backlight control
|
||||
#define LCD_BACKLIGHT 0x08
|
||||
#define LCD_NOBACKLIGHT 0x00
|
||||
|
||||
//========================================================================
|
||||
//Begin of I2CTinyLCD Library for Dual LCD by KD8CEC
|
||||
//========================================================================
|
||||
#ifdef UBITX_DISPLAY_LCD1602I_DUAL
|
||||
|
||||
#include <Wire.h>
|
||||
/*************************************************************************
|
||||
I2C Tiny LCD Library
|
||||
Referecnce Source : LiquidCrystal_I2C.cpp // Based on the work by DFRobot
|
||||
KD8CEC
|
||||
|
||||
This source code is modified version for small program memory
|
||||
from Arduino LiquidCrystal_I2C Library
|
||||
|
||||
I wrote this code myself, so there is no license restriction.
|
||||
So this code allows anyone to write with confidence.
|
||||
But keep it as long as the original author of the code.
|
||||
Ian KD8CEC
|
||||
**************************************************************************/
|
||||
#define UBITX_DISPLAY_LCD1602_BASE
|
||||
|
||||
#define En B00000100 // Enable bit
|
||||
#define Rw B00000010 // Read/Write bit
|
||||
#define Rs B00000001 // Register select bit
|
||||
|
||||
#define LCD_Command(x) (LCD_Send(x, 0))
|
||||
#define LCD_Write(x) (LCD_Send(x, Rs))
|
||||
|
||||
uint8_t _Addr;
|
||||
uint8_t _displayfunction;
|
||||
uint8_t _displaycontrol;
|
||||
uint8_t _displaymode;
|
||||
uint8_t _numlines;
|
||||
uint8_t _cols;
|
||||
uint8_t _rows;
|
||||
uint8_t _backlightval;
|
||||
|
||||
#define printIIC(args) Wire.write(args)
|
||||
|
||||
void expanderWrite(uint8_t _data)
|
||||
{
|
||||
Wire.beginTransmission(_Addr);
|
||||
printIIC((int)(_data) | _backlightval);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void pulseEnable(uint8_t _data){
|
||||
expanderWrite(_data | En); // En high
|
||||
delayMicroseconds(1); // enable pulse must be >450ns
|
||||
|
||||
expanderWrite(_data & ~En); // En low
|
||||
delayMicroseconds(50); // commands need > 37us to settle
|
||||
}
|
||||
|
||||
void write4bits(uint8_t value)
|
||||
{
|
||||
expanderWrite(value);
|
||||
pulseEnable(value);
|
||||
}
|
||||
|
||||
void LCD_Send(uint8_t value, uint8_t mode)
|
||||
{
|
||||
uint8_t highnib=value&0xf0;
|
||||
uint8_t lownib=(value<<4)&0xf0;
|
||||
write4bits((highnib)|mode);
|
||||
write4bits((lownib)|mode);
|
||||
}
|
||||
|
||||
|
||||
// Turn the (optional) backlight off/on
|
||||
void noBacklight(void) {
|
||||
_backlightval=LCD_NOBACKLIGHT;
|
||||
expanderWrite(0);
|
||||
}
|
||||
|
||||
void backlight(void) {
|
||||
_backlightval=LCD_BACKLIGHT;
|
||||
expanderWrite(0);
|
||||
}
|
||||
|
||||
void LCD1602_Dual_Init()
|
||||
{
|
||||
//I2C Init
|
||||
_cols = 16;
|
||||
_rows = 2;
|
||||
_backlightval = LCD_NOBACKLIGHT;
|
||||
Wire.begin();
|
||||
|
||||
delay(50);
|
||||
|
||||
// Now we pull both RS and R/W low to begin commands
|
||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
||||
expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
|
||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
||||
expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
|
||||
delay(1000);
|
||||
//put the LCD into 4 bit mode
|
||||
// this is according to the hitachi HD44780 datasheet
|
||||
// figure 24, pg 46
|
||||
|
||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
||||
// we start in 8bit mode, try to set 4 bit mode
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// second try
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// third go!
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(150);
|
||||
|
||||
// finally, set to 4-bit interface
|
||||
write4bits(0x02 << 4);
|
||||
|
||||
// finally, set # lines, font size, etc.
|
||||
LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE);
|
||||
|
||||
// turn the display on with no cursor or blinking default
|
||||
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
|
||||
|
||||
// clear it off
|
||||
LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||
//delayMicroseconds(2000); // this command takes a long time!
|
||||
delayMicroseconds(1000); // this command takes a long time!
|
||||
|
||||
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
|
||||
|
||||
backlight();
|
||||
|
||||
|
||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
||||
// we start in 8bit mode, try to set 4 bit mode
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// second try
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// third go!
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(150);
|
||||
|
||||
// finally, set to 4-bit interface
|
||||
write4bits(0x02 << 4);
|
||||
|
||||
// finally, set # lines, font size, etc.
|
||||
LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE);
|
||||
|
||||
// turn the display on with no cursor or blinking default
|
||||
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
|
||||
|
||||
// clear it off
|
||||
LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||
//delayMicroseconds(2000); // this command takes a long time!
|
||||
delayMicroseconds(1000); // this command takes a long time!
|
||||
|
||||
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
|
||||
|
||||
backlight();
|
||||
|
||||
//Change to Default LCD (Master)
|
||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// 16 X 02 LCD Routines
|
||||
//Begin of Display Base Routines (Init, printLine..)
|
||||
//========================================================================
|
||||
|
||||
void LCD_Print(const char *c)
|
||||
{
|
||||
for (uint8_t i = 0; i < strlen(c); i++)
|
||||
{
|
||||
if (*(c + i) == 0x00) return;
|
||||
LCD_Write(*(c + i));
|
||||
}
|
||||
}
|
||||
|
||||
const int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
|
||||
void LCD_SetCursor(uint8_t col, uint8_t row)
|
||||
{
|
||||
LCD_Command(LCD_SETDDRAMADDR | (col + row_offsets[row])); //0 : 0x00, 1 : 0x40, only for 20 x 4 lcd
|
||||
}
|
||||
|
||||
void LCD_CreateChar(uint8_t location, uint8_t charmap[])
|
||||
{
|
||||
location &= 0x7; // we only have 8 locations 0-7
|
||||
LCD_Command(LCD_SETCGRAMADDR | (location << 3));
|
||||
for (int i=0; i<8; i++)
|
||||
LCD_Write(charmap[i]);
|
||||
}
|
||||
|
||||
//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA
|
||||
//#define OPTION_SKINNYBARS
|
||||
|
||||
char c[30], b[30];
|
||||
char printBuff[4][20]; //mirrors what is showing on the two lines of the display
|
||||
|
||||
void LCD_Init(void)
|
||||
{
|
||||
LCD1602_Dual_Init();
|
||||
|
||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
||||
initMeter(); //for Meter Display //when dual LCD, S.Meter on second LCD
|
||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
||||
}
|
||||
|
||||
|
||||
// The generic routine to display one line on the LCD
|
||||
void printLine(unsigned char linenmbr, const char *c) {
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||
if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change
|
||||
LCD_SetCursor(0, linenmbr); // place the cursor at the beginning of the selected line
|
||||
LCD_Print(c);
|
||||
strcpy(printBuff[linenmbr], c);
|
||||
|
||||
for (byte i = strlen(c); i < 20; i++) { // add white spaces until the end of the 20 characters line is reached
|
||||
LCD_Write(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printLineF(char linenmbr, const __FlashStringHelper *c)
|
||||
{
|
||||
int i;
|
||||
char tmpBuff[21];
|
||||
PGM_P p = reinterpret_cast<PGM_P>(c);
|
||||
|
||||
for (i = 0; i < 21; i++){
|
||||
unsigned char fChar = pgm_read_byte(p++);
|
||||
tmpBuff[i] = fChar;
|
||||
if (fChar == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
printLine(linenmbr, tmpBuff);
|
||||
}
|
||||
|
||||
#define LCD_MAX_COLUMN 20
|
||||
void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) {
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||
|
||||
LCD_SetCursor(lcdColumn, linenmbr);
|
||||
|
||||
for (byte i = eepromStartIndex; i <= eepromEndIndex; i++)
|
||||
{
|
||||
if (++lcdColumn <= LCD_MAX_COLUMN)
|
||||
LCD_Write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (byte i = lcdColumn; i < 20; i++) //Right Padding by Space
|
||||
LCD_Write(' ');
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1(const char *c)
|
||||
{
|
||||
printLine(1,c);
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2(const char *c)
|
||||
{
|
||||
printLine(0,c);
|
||||
}
|
||||
|
||||
void clearLine2()
|
||||
{
|
||||
printLine2("");
|
||||
line2DisplayStatus = 0;
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1Clear(){
|
||||
printLine(1,"");
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2Clear(){
|
||||
printLine(0, "");
|
||||
}
|
||||
|
||||
void printLine2ClearAndUpdate(){
|
||||
printLine(0, "");
|
||||
line2DisplayStatus = 0;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
//==================================================================================
|
||||
//End of Display Base Routines
|
||||
//==================================================================================
|
||||
|
||||
|
||||
//==================================================================================
|
||||
//Begin of User Interface Routines
|
||||
//==================================================================================
|
||||
|
||||
//Main Display
|
||||
// this builds up the top line of the display with frequency and mode
|
||||
void updateDisplay() {
|
||||
// tks Jack Purdum W8TEE
|
||||
// replaced fsprint commmands by str commands for code size reduction
|
||||
// replace code for Frequency numbering error (alignment, point...) by KD8CEC
|
||||
// i also Very TNX Purdum for good source code
|
||||
int i;
|
||||
unsigned long tmpFreq = frequency; //
|
||||
|
||||
memset(c, 0, sizeof(c));
|
||||
|
||||
if (inTx){
|
||||
if (isCWAutoMode == 2) {
|
||||
for (i = 0; i < 4; i++)
|
||||
c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' ');
|
||||
|
||||
//display Sending Index
|
||||
c[4] = byteToChar(sendingCWTextIndex);
|
||||
c[5] = '=';
|
||||
}
|
||||
else {
|
||||
if (cwTimeout > 0)
|
||||
strcpy(c, " CW:");
|
||||
else
|
||||
strcpy(c, " TX:");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ritOn)
|
||||
strcpy(c, "RIT ");
|
||||
else {
|
||||
if (cwMode == 0)
|
||||
{
|
||||
if (isUSB)
|
||||
strcpy(c, "USB ");
|
||||
else
|
||||
strcpy(c, "LSB ");
|
||||
}
|
||||
else if (cwMode == 1)
|
||||
{
|
||||
strcpy(c, "CWL ");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(c, "CWU ");
|
||||
}
|
||||
}
|
||||
|
||||
if (vfoActive == VFO_A) // VFO A is active
|
||||
strcat(c, "A:");
|
||||
else
|
||||
strcat(c, "B:");
|
||||
}
|
||||
|
||||
//Fixed by Mitani Massaru (JE4SMQ)
|
||||
if (isShiftDisplayCWFreq == 1)
|
||||
{
|
||||
if (cwMode == 1) //CWL
|
||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
||||
else if (cwMode == 2) //CWU
|
||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
||||
}
|
||||
|
||||
//display frequency
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) c[i] = '.';
|
||||
else {
|
||||
c[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
c[i] = ' ';
|
||||
}
|
||||
|
||||
//remarked by KD8CEC
|
||||
//already RX/TX status display, and over index (16 x 2 LCD)
|
||||
printLine(1, c);
|
||||
|
||||
byte diplayVFOLine = 1;
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayVFOLine = 0;
|
||||
|
||||
if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) ||
|
||||
(vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) {
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write((uint8_t)0);
|
||||
}
|
||||
else if (isCWAutoMode == 2){
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write(0x7E);
|
||||
}
|
||||
else
|
||||
{
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write(':');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char line2Buffer[20];
|
||||
//KD8CEC 200Hz ST
|
||||
//L14.150 200Hz ST
|
||||
//U14.150 +150khz
|
||||
int freqScrollPosition = 0;
|
||||
|
||||
//Example Line2 Optinal Display
|
||||
//immediate execution, not call by scheulder
|
||||
//warning : unused parameter 'displayType' <-- ignore, this is reserve
|
||||
void updateLine2Buffer(char displayType)
|
||||
{
|
||||
unsigned long tmpFreq = 0;
|
||||
if (ritOn)
|
||||
{
|
||||
strcpy(line2Buffer, "RitTX:");
|
||||
|
||||
//display frequency
|
||||
tmpFreq = ritTxFrequency;
|
||||
|
||||
//Fixed by Mitani Massaru (JE4SMQ)
|
||||
if (isShiftDisplayCWFreq == 1)
|
||||
{
|
||||
if (cwMode == 1) //CWL
|
||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
||||
else if (cwMode == 2) //CWU
|
||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
||||
}
|
||||
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
return;
|
||||
} //end of ritOn display
|
||||
|
||||
//other VFO display
|
||||
if (vfoActive == VFO_B)
|
||||
{
|
||||
tmpFreq = vfoA;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpFreq = vfoB;
|
||||
}
|
||||
|
||||
// EXAMPLE 1 & 2
|
||||
//U14.150.100
|
||||
//display frequency
|
||||
for (int i = 9; i >= 0; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 2 || i == 6) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
memset(&line2Buffer[10], ' ', 10);
|
||||
|
||||
if (isIFShift)
|
||||
{
|
||||
line2Buffer[6] = 'M';
|
||||
line2Buffer[7] = ' ';
|
||||
//IFShift Offset Value
|
||||
line2Buffer[8] = 'I';
|
||||
line2Buffer[9] = 'F';
|
||||
|
||||
line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0;
|
||||
line2Buffer[11] = 0;
|
||||
line2Buffer[12] = ' ';
|
||||
|
||||
//11, 12, 13, 14, 15
|
||||
memset(b, 0, sizeof(b));
|
||||
ltoa(ifShiftValue, b, DEC);
|
||||
strncat(line2Buffer, b, 5);
|
||||
|
||||
for (int i = 12; i < 17; i++)
|
||||
{
|
||||
if (line2Buffer[i] == 0)
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
} // end of display IF
|
||||
else // step & Key Type display
|
||||
{
|
||||
//Step
|
||||
long tmpStep = arTuneStep[tuneStepIndex -1];
|
||||
|
||||
byte isStepKhz = 0;
|
||||
if (tmpStep >= 1000)
|
||||
{
|
||||
isStepKhz = 2;
|
||||
}
|
||||
|
||||
for (int i = 13; i >= 11 - isStepKhz; i--) {
|
||||
if (tmpStep > 0) {
|
||||
line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30;
|
||||
tmpStep /= 10;
|
||||
}
|
||||
else
|
||||
line2Buffer[i +isStepKhz] = ' ';
|
||||
}
|
||||
|
||||
if (isStepKhz == 0)
|
||||
{
|
||||
line2Buffer[14] = 'H';
|
||||
line2Buffer[15] = 'z';
|
||||
}
|
||||
}
|
||||
|
||||
//line2Buffer[17] = ' ';
|
||||
/* ianlee
|
||||
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
||||
if (cwKeyType == 0)
|
||||
{
|
||||
line2Buffer[18] = 'S';
|
||||
line2Buffer[19] = 'T';
|
||||
}
|
||||
else if (cwKeyType == 1)
|
||||
{
|
||||
line2Buffer[18] = 'I';
|
||||
line2Buffer[19] = 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
line2Buffer[18] = 'I';
|
||||
line2Buffer[19] = 'B';
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
//meterType : 0 = S.Meter, 1 : P.Meter
|
||||
void DisplayMeter(byte meterType, byte meterValue, char drawPosition)
|
||||
{
|
||||
if (meterType == 0 || meterType == 1 || meterType == 2)
|
||||
{
|
||||
drawMeter(meterValue);
|
||||
|
||||
LCD_SetCursor(drawPosition, 0);
|
||||
LCD_Write('S');
|
||||
|
||||
LCD_Write(':');
|
||||
for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6
|
||||
LCD_Write(lcdMeter[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
byte testValue = 0;
|
||||
char checkCount = 0;
|
||||
|
||||
int currentSMeter = 0;
|
||||
byte scaledSMeter = 0;
|
||||
char checkCountSMeter = 0;
|
||||
|
||||
char beforeKeyType = -1;
|
||||
char displaySDRON = 0;
|
||||
|
||||
//execute interval : 0.25sec
|
||||
void idle_process()
|
||||
{
|
||||
//space for user graphic display
|
||||
if (menuOn == 0)
|
||||
{
|
||||
if ((displayOption1 & 0x10) == 0x10) //always empty topline
|
||||
return;
|
||||
|
||||
//if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message
|
||||
if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) {
|
||||
if (checkCount++ > 1)
|
||||
{
|
||||
updateLine2Buffer(0); //call by scheduler
|
||||
printLine2(line2Buffer);
|
||||
line2DisplayStatus = 2;
|
||||
checkCount = 0;
|
||||
|
||||
//check change CW Key Type
|
||||
if (beforeKeyType != cwKeyType)
|
||||
{
|
||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
||||
LCD_SetCursor(10, 0);
|
||||
LCD_Write('K');
|
||||
LCD_Write('E');
|
||||
LCD_Write('Y');
|
||||
LCD_Write(':');
|
||||
|
||||
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
||||
if (cwKeyType == 0)
|
||||
{
|
||||
LCD_Write('S');
|
||||
LCD_Write('T');
|
||||
}
|
||||
else if (cwKeyType == 1)
|
||||
{
|
||||
LCD_Write('I');
|
||||
LCD_Write('A');
|
||||
}
|
||||
else
|
||||
{
|
||||
LCD_Write('I');
|
||||
LCD_Write('B');
|
||||
}
|
||||
|
||||
beforeKeyType = cwKeyType;
|
||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
||||
} //Display Second Screen
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//EX for Meters
|
||||
|
||||
//S-Meter Display
|
||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
||||
if (sdrModeOn == 1)
|
||||
{
|
||||
if (displaySDRON == 0) //once display
|
||||
{
|
||||
displaySDRON = 1;
|
||||
LCD_SetCursor(0, 0);
|
||||
LCD_Write('S');
|
||||
LCD_Write('D');
|
||||
LCD_Write('R');
|
||||
LCD_Write(' ');
|
||||
LCD_Write('M');
|
||||
LCD_Write('O');
|
||||
LCD_Write('D');
|
||||
LCD_Write('E');
|
||||
}
|
||||
}
|
||||
else if (((displayOption1 & 0x08) == 0x08) && (++checkCountSMeter > 3))
|
||||
{
|
||||
int newSMeter;
|
||||
displaySDRON = 0;
|
||||
|
||||
//VK2ETA S-Meter from MAX9814 TC pin
|
||||
newSMeter = analogRead(ANALOG_SMETER);
|
||||
|
||||
//Faster attack, Slower release
|
||||
//currentSMeter = (newSMeter > currentSMeter ? ((currentSMeter * 3 + newSMeter * 7) + 5) / 10 : ((currentSMeter * 7 + newSMeter * 3) + 5) / 10);
|
||||
currentSMeter = (currentSMeter * 3 + newSMeter * 7) / 10; //remarked becaused of have already Latency time
|
||||
|
||||
scaledSMeter = 0;
|
||||
for (byte s = 8; s >= 1; s--) {
|
||||
if (currentSMeter > sMeterLevels[s]) {
|
||||
scaledSMeter = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DisplayMeter(0, scaledSMeter, 0);
|
||||
|
||||
checkCountSMeter = 0;
|
||||
} //end of S-Meter
|
||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//AutoKey LCD Display Routine
|
||||
void Display_AutoKeyTextIndex(byte textIndex)
|
||||
{
|
||||
byte diplayAutoCWLine = 0;
|
||||
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayAutoCWLine = 1;
|
||||
LCD_SetCursor(0, diplayAutoCWLine);
|
||||
LCD_Write(byteToChar(textIndex));
|
||||
LCD_Write(':');
|
||||
}
|
||||
|
||||
void DisplayCallsign(byte callSignLength)
|
||||
{
|
||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
||||
printLineFromEEPRom(1, 16 - userCallsignLength, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT)
|
||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
||||
}
|
||||
|
||||
void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo)
|
||||
{
|
||||
_Addr = I2C_LCD_SECOND_ADDRESS;
|
||||
printLineF(1, fwVersionInfo);
|
||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,855 +0,0 @@
|
||||
/*************************************************************************
|
||||
KD8CEC's uBITX Display Routine for LCD2004 Parrel
|
||||
1.This is the display code for the default LCD mounted in uBITX.
|
||||
2.Display related functions of uBITX. Some functions moved from uBITX_Ui.
|
||||
3.uBITX Idle time Processing
|
||||
Functions that run at times that do not affect TX, CW, and CAT
|
||||
It is called in 1/10 time unit.
|
||||
-----------------------------------------------------------------------------
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
**************************************************************************/
|
||||
#include "ubitx.h"
|
||||
|
||||
//Common Defines *********************************************************
|
||||
#define LCD_CLEARDISPLAY 0x01
|
||||
#define LCD_RETURNHOME 0x02
|
||||
#define LCD_ENTRYMODESET 0x04
|
||||
#define LCD_DISPLAYCONTROL 0x08
|
||||
#define LCD_CURSORSHIFT 0x10
|
||||
#define LCD_FUNCTIONSET 0x20
|
||||
#define LCD_SETCGRAMADDR 0x40
|
||||
#define LCD_SETDDRAMADDR 0x80
|
||||
|
||||
// flags for display entry mode
|
||||
#define LCD_ENTRYRIGHT 0x00
|
||||
#define LCD_ENTRYLEFT 0x02
|
||||
#define LCD_ENTRYSHIFTINCREMENT 0x01
|
||||
#define LCD_ENTRYSHIFTDECREMENT 0x00
|
||||
|
||||
// flags for display on/off control
|
||||
#define LCD_DISPLAYON 0x04
|
||||
#define LCD_DISPLAYOFF 0x00
|
||||
#define LCD_CURSORON 0x02
|
||||
#define LCD_CURSOROFF 0x00
|
||||
#define LCD_BLINKON 0x01
|
||||
#define LCD_BLINKOFF 0x00
|
||||
|
||||
// flags for display/cursor shift
|
||||
#define LCD_DISPLAYMOVE 0x08
|
||||
#define LCD_CURSORMOVE 0x00
|
||||
#define LCD_MOVERIGHT 0x04
|
||||
#define LCD_MOVELEFT 0x00
|
||||
|
||||
// flags for function set
|
||||
#define LCD_8BITMODE 0x10
|
||||
#define LCD_4BITMODE 0x00
|
||||
#define LCD_2LINE 0x08
|
||||
#define LCD_1LINE 0x00
|
||||
#define LCD_5x10DOTS 0x04
|
||||
#define LCD_5x8DOTS 0x00
|
||||
|
||||
// flags for backlight control
|
||||
#define LCD_BACKLIGHT 0x08
|
||||
#define LCD_NOBACKLIGHT 0x00
|
||||
|
||||
//========================================================================
|
||||
//Begin of TinyLCD Library by KD8CEC
|
||||
//========================================================================
|
||||
|
||||
#ifdef UBITX_DISPLAY_LCD2004P
|
||||
/*************************************************************************
|
||||
LCD2004TINY Library for 20 x 4 LCD
|
||||
Referecnce Source : LiquidCrystal.cpp
|
||||
KD8CEC
|
||||
|
||||
This source code is modified version for small program memory
|
||||
from Arduino LiquidCrystal Library
|
||||
|
||||
I wrote this code myself, so there is no license restriction.
|
||||
So this code allows anyone to write with confidence.
|
||||
But keep it as long as the original author of the code.
|
||||
DE Ian KD8CEC
|
||||
**************************************************************************/
|
||||
#define LCD_Command(x) (LCD_Send(x, LOW))
|
||||
#define LCD_Write(x) (LCD_Send(x, HIGH))
|
||||
|
||||
#define UBITX_DISPLAY_LCD2004_BASE
|
||||
|
||||
//Define connected PIN
|
||||
#define LCD_PIN_RS 8
|
||||
#define LCD_PIN_EN 9
|
||||
uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13};
|
||||
|
||||
void write4bits(uint8_t value)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
digitalWrite(LCD_PIN_DAT[i], (value >> i) & 0x01);
|
||||
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(LCD_PIN_EN, HIGH);
|
||||
delayMicroseconds(1); // enable pulse must be >450ns
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
delayMicroseconds(100); // commands need > 37us to settle
|
||||
}
|
||||
|
||||
void LCD_Send(uint8_t value, uint8_t mode)
|
||||
{
|
||||
digitalWrite(LCD_PIN_RS, mode);
|
||||
write4bits(value>>4);
|
||||
write4bits(value);
|
||||
}
|
||||
|
||||
void LCD2004_Init()
|
||||
{
|
||||
pinMode(LCD_PIN_RS, OUTPUT);
|
||||
pinMode(LCD_PIN_EN, OUTPUT);
|
||||
for (int i = 0; i < 4; i++)
|
||||
pinMode(LCD_PIN_DAT[i], OUTPUT);
|
||||
|
||||
delayMicroseconds(50);
|
||||
|
||||
// Now we pull both RS and R/W low to begin commands
|
||||
digitalWrite(LCD_PIN_RS, LOW);
|
||||
digitalWrite(LCD_PIN_EN, LOW);
|
||||
|
||||
// we start in 8bit mode, try to set 4 bit mode
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// second try
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// third go!
|
||||
write4bits(0x03);
|
||||
delayMicroseconds(150);
|
||||
|
||||
// finally, set to 4-bit interface
|
||||
write4bits(0x02);
|
||||
|
||||
// finally, set # lines, font size, etc.
|
||||
LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE);
|
||||
|
||||
// turn the display on with no cursor or blinking default
|
||||
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
|
||||
|
||||
// clear it off
|
||||
LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||
delayMicroseconds(2000); // this command takes a long time!
|
||||
|
||||
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
|
||||
}
|
||||
#endif
|
||||
//========================================================================
|
||||
//End of TinyLCD Library by KD8CEC
|
||||
//========================================================================
|
||||
|
||||
|
||||
|
||||
//========================================================================
|
||||
//Begin of I2CTinyLCD Library by KD8CEC
|
||||
//========================================================================
|
||||
#ifdef UBITX_DISPLAY_LCD2004I
|
||||
|
||||
#include <Wire.h>
|
||||
/*************************************************************************
|
||||
I2C Tiny LCD Library
|
||||
Referecnce Source : LiquidCrystal_I2C.cpp // Based on the work by DFRobot
|
||||
KD8CEC
|
||||
|
||||
This source code is modified version for small program memory
|
||||
from Arduino LiquidCrystal_I2C Library
|
||||
|
||||
I wrote this code myself, so there is no license restriction.
|
||||
So this code allows anyone to write with confidence.
|
||||
But keep it as long as the original author of the code.
|
||||
Ian KD8CEC
|
||||
**************************************************************************/
|
||||
#define UBITX_DISPLAY_LCD2004_BASE
|
||||
|
||||
#define En B00000100 // Enable bit
|
||||
#define Rw B00000010 // Read/Write bit
|
||||
#define Rs B00000001 // Register select bit
|
||||
|
||||
#define LCD_Command(x) (LCD_Send(x, 0))
|
||||
#define LCD_Write(x) (LCD_Send(x, Rs))
|
||||
|
||||
uint8_t _Addr;
|
||||
uint8_t _displayfunction;
|
||||
uint8_t _displaycontrol;
|
||||
uint8_t _displaymode;
|
||||
uint8_t _numlines;
|
||||
uint8_t _cols;
|
||||
uint8_t _rows;
|
||||
uint8_t _backlightval;
|
||||
|
||||
#define printIIC(args) Wire.write(args)
|
||||
|
||||
void expanderWrite(uint8_t _data)
|
||||
{
|
||||
Wire.beginTransmission(_Addr);
|
||||
printIIC((int)(_data) | _backlightval);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void pulseEnable(uint8_t _data){
|
||||
expanderWrite(_data | En); // En high
|
||||
delayMicroseconds(1); // enable pulse must be >450ns
|
||||
|
||||
expanderWrite(_data & ~En); // En low
|
||||
delayMicroseconds(50); // commands need > 37us to settle
|
||||
}
|
||||
|
||||
void write4bits(uint8_t value)
|
||||
{
|
||||
expanderWrite(value);
|
||||
pulseEnable(value);
|
||||
}
|
||||
|
||||
void LCD_Send(uint8_t value, uint8_t mode)
|
||||
{
|
||||
uint8_t highnib=value&0xf0;
|
||||
uint8_t lownib=(value<<4)&0xf0;
|
||||
write4bits((highnib)|mode);
|
||||
write4bits((lownib)|mode);
|
||||
}
|
||||
|
||||
|
||||
// Turn the (optional) backlight off/on
|
||||
void noBacklight(void) {
|
||||
_backlightval=LCD_NOBACKLIGHT;
|
||||
expanderWrite(0);
|
||||
}
|
||||
|
||||
void backlight(void) {
|
||||
_backlightval=LCD_BACKLIGHT;
|
||||
expanderWrite(0);
|
||||
}
|
||||
|
||||
void LCD2004_Init()
|
||||
{
|
||||
//I2C Init
|
||||
_Addr = I2C_LCD_MASTER_ADDRESS;
|
||||
_cols = 20;
|
||||
_rows = 4;
|
||||
_backlightval = LCD_NOBACKLIGHT;
|
||||
Wire.begin();
|
||||
|
||||
delay(50);
|
||||
|
||||
// Now we pull both RS and R/W low to begin commands
|
||||
expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
|
||||
delay(1000);
|
||||
//put the LCD into 4 bit mode
|
||||
// this is according to the hitachi HD44780 datasheet
|
||||
// figure 24, pg 46
|
||||
|
||||
// we start in 8bit mode, try to set 4 bit mode
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// second try
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// third go!
|
||||
write4bits(0x03 << 4);
|
||||
delayMicroseconds(150);
|
||||
|
||||
// finally, set to 4-bit interface
|
||||
write4bits(0x02 << 4);
|
||||
|
||||
// finally, set # lines, font size, etc.
|
||||
LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE);
|
||||
|
||||
// turn the display on with no cursor or blinking default
|
||||
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
|
||||
|
||||
// clear it off
|
||||
LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||
//delayMicroseconds(2000); // this command takes a long time!
|
||||
delayMicroseconds(1000); // this command takes a long time!
|
||||
|
||||
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
|
||||
|
||||
backlight();
|
||||
}
|
||||
#endif
|
||||
//========================================================================
|
||||
//End of I2CTinyLCD Library by KD8CEC
|
||||
//========================================================================
|
||||
|
||||
|
||||
//========================================================================
|
||||
// 20 X 04 LCD Routines
|
||||
//Begin of Display Base Routines (Init, printLine..)
|
||||
//========================================================================
|
||||
#ifdef UBITX_DISPLAY_LCD2004_BASE
|
||||
|
||||
void LCD_Print(const char *c)
|
||||
{
|
||||
for (uint8_t i = 0; i < strlen(c); i++)
|
||||
{
|
||||
if (*(c + i) == 0x00) return;
|
||||
LCD_Write(*(c + i));
|
||||
}
|
||||
}
|
||||
|
||||
const int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
|
||||
void LCD_SetCursor(uint8_t col, uint8_t row)
|
||||
{
|
||||
LCD_Command(LCD_SETDDRAMADDR | (col + row_offsets[row])); //0 : 0x00, 1 : 0x40, only for 20 x 4 lcd
|
||||
}
|
||||
|
||||
void LCD_CreateChar(uint8_t location, uint8_t charmap[])
|
||||
{
|
||||
location &= 0x7; // we only have 8 locations 0-7
|
||||
LCD_Command(LCD_SETCGRAMADDR | (location << 3));
|
||||
for (int i=0; i<8; i++)
|
||||
LCD_Write(charmap[i]);
|
||||
}
|
||||
|
||||
//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA
|
||||
//#define OPTION_SKINNYBARS
|
||||
|
||||
char c[30], b[30];
|
||||
char printBuff[4][21]; //mirrors what is showing on the two lines of the display
|
||||
|
||||
void LCD_Init(void)
|
||||
{
|
||||
LCD2004_Init();
|
||||
initMeter(); //for Meter Display
|
||||
}
|
||||
|
||||
|
||||
// The generic routine to display one line on the LCD
|
||||
void printLine(unsigned char linenmbr, const char *c) {
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||
if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change
|
||||
LCD_SetCursor(0, linenmbr); // place the cursor at the beginning of the selected line
|
||||
LCD_Print(c);
|
||||
strcpy(printBuff[linenmbr], c);
|
||||
|
||||
for (byte i = strlen(c); i < 20; i++) { // add white spaces until the end of the 20 characters line is reached
|
||||
LCD_Write(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printLineF(char linenmbr, const __FlashStringHelper *c)
|
||||
{
|
||||
int i;
|
||||
char tmpBuff[21];
|
||||
PGM_P p = reinterpret_cast<PGM_P>(c);
|
||||
|
||||
for (i = 0; i < 21; i++){
|
||||
unsigned char fChar = pgm_read_byte(p++);
|
||||
tmpBuff[i] = fChar;
|
||||
if (fChar == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
printLine(linenmbr, tmpBuff);
|
||||
}
|
||||
|
||||
#define LCD_MAX_COLUMN 20
|
||||
void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) {
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
|
||||
|
||||
LCD_SetCursor(lcdColumn, linenmbr);
|
||||
|
||||
for (byte i = eepromStartIndex; i <= eepromEndIndex; i++)
|
||||
{
|
||||
if (++lcdColumn <= LCD_MAX_COLUMN)
|
||||
LCD_Write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (byte i = lcdColumn; i < 20; i++) //Right Padding by Space
|
||||
LCD_Write(' ');
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1(const char *c)
|
||||
{
|
||||
printLine(1,c);
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2(const char *c)
|
||||
{
|
||||
printLine(0,c);
|
||||
}
|
||||
|
||||
void clearLine2()
|
||||
{
|
||||
printLine2("");
|
||||
line2DisplayStatus = 0;
|
||||
}
|
||||
|
||||
// short cut to print to the first line
|
||||
void printLine1Clear(){
|
||||
printLine(1,"");
|
||||
}
|
||||
// short cut to print to the first line
|
||||
void printLine2Clear(){
|
||||
printLine(0, "");
|
||||
}
|
||||
|
||||
void printLine2ClearAndUpdate(){
|
||||
printLine(0, "");
|
||||
line2DisplayStatus = 0;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
//==================================================================================
|
||||
//End of Display Base Routines
|
||||
//==================================================================================
|
||||
|
||||
|
||||
//==================================================================================
|
||||
//Begin of User Interface Routines
|
||||
//==================================================================================
|
||||
|
||||
//Main Display
|
||||
// this builds up the top line of the display with frequency and mode
|
||||
void updateDisplay() {
|
||||
// tks Jack Purdum W8TEE
|
||||
// replaced fsprint commmands by str commands for code size reduction
|
||||
// replace code for Frequency numbering error (alignment, point...) by KD8CEC
|
||||
// i also Very TNX Purdum for good source code
|
||||
int i;
|
||||
unsigned long tmpFreq = frequency; //
|
||||
|
||||
memset(c, 0, sizeof(c));
|
||||
|
||||
if (inTx){
|
||||
if (isCWAutoMode == 2) {
|
||||
for (i = 0; i < 4; i++)
|
||||
c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' ');
|
||||
|
||||
//display Sending Index
|
||||
c[4] = byteToChar(sendingCWTextIndex);
|
||||
c[5] = '=';
|
||||
}
|
||||
else {
|
||||
if (cwTimeout > 0)
|
||||
strcpy(c, " CW:");
|
||||
else
|
||||
strcpy(c, " TX:");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ritOn)
|
||||
strcpy(c, "RIT ");
|
||||
else {
|
||||
if (cwMode == 0)
|
||||
{
|
||||
if (isUSB)
|
||||
strcpy(c, "USB ");
|
||||
else
|
||||
strcpy(c, "LSB ");
|
||||
}
|
||||
else if (cwMode == 1)
|
||||
{
|
||||
strcpy(c, "CWL ");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(c, "CWU ");
|
||||
}
|
||||
}
|
||||
|
||||
if (vfoActive == VFO_A) // VFO A is active
|
||||
strcat(c, "A:");
|
||||
else
|
||||
strcat(c, "B:");
|
||||
}
|
||||
|
||||
//Fixed by Mitani Massaru (JE4SMQ)
|
||||
if (isShiftDisplayCWFreq == 1)
|
||||
{
|
||||
if (cwMode == 1) //CWL
|
||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
||||
else if (cwMode == 2) //CWU
|
||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
||||
}
|
||||
|
||||
//display frequency
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) c[i] = '.';
|
||||
else {
|
||||
c[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
c[i] = ' ';
|
||||
}
|
||||
|
||||
if (sdrModeOn)
|
||||
strcat(c, " SDR");
|
||||
else
|
||||
strcat(c, " SPK");
|
||||
|
||||
//remarked by KD8CEC
|
||||
//already RX/TX status display, and over index (20 x 4 LCD)
|
||||
//if (inTx)
|
||||
// strcat(c, " TX");
|
||||
printLine(1, c);
|
||||
|
||||
byte diplayVFOLine = 1;
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayVFOLine = 0;
|
||||
|
||||
if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) ||
|
||||
(vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) {
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write((uint8_t)0);
|
||||
}
|
||||
else if (isCWAutoMode == 2){
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write(0x7E);
|
||||
}
|
||||
else
|
||||
{
|
||||
LCD_SetCursor(5,diplayVFOLine);
|
||||
LCD_Write(':');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char line2Buffer[20];
|
||||
//KD8CEC 200Hz ST
|
||||
//L14.150 200Hz ST
|
||||
//U14.150 +150khz
|
||||
int freqScrollPosition = 0;
|
||||
|
||||
//Example Line2 Optinal Display
|
||||
//immediate execution, not call by scheulder
|
||||
//warning : unused parameter 'displayType' <-- ignore, this is reserve
|
||||
void updateLine2Buffer(char displayType)
|
||||
{
|
||||
unsigned long tmpFreq = 0;
|
||||
if (ritOn)
|
||||
{
|
||||
strcpy(line2Buffer, "RitTX:");
|
||||
|
||||
//display frequency
|
||||
tmpFreq = ritTxFrequency;
|
||||
|
||||
//Fixed by Mitani Massaru (JE4SMQ)
|
||||
if (isShiftDisplayCWFreq == 1)
|
||||
{
|
||||
if (cwMode == 1) //CWL
|
||||
tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal;
|
||||
else if (cwMode == 2) //CWU
|
||||
tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal;
|
||||
}
|
||||
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 12 || i == 8) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
return;
|
||||
} //end of ritOn display
|
||||
|
||||
//other VFO display
|
||||
if (vfoActive == VFO_B)
|
||||
{
|
||||
tmpFreq = vfoA;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpFreq = vfoB;
|
||||
}
|
||||
|
||||
// EXAMPLE 1 & 2
|
||||
//U14.150.100
|
||||
//display frequency
|
||||
for (int i = 9; i >= 0; i--) {
|
||||
if (tmpFreq > 0) {
|
||||
if (i == 2 || i == 6) line2Buffer[i] = '.';
|
||||
else {
|
||||
line2Buffer[i] = tmpFreq % 10 + 0x30;
|
||||
tmpFreq /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
|
||||
memset(&line2Buffer[10], ' ', 10);
|
||||
|
||||
if (isIFShift)
|
||||
{
|
||||
line2Buffer[6] = 'M';
|
||||
line2Buffer[7] = ' ';
|
||||
//IFShift Offset Value
|
||||
line2Buffer[8] = 'I';
|
||||
line2Buffer[9] = 'F';
|
||||
|
||||
line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0;
|
||||
line2Buffer[11] = 0;
|
||||
line2Buffer[12] = ' ';
|
||||
|
||||
//11, 12, 13, 14, 15
|
||||
memset(b, 0, sizeof(b));
|
||||
ltoa(ifShiftValue, b, DEC);
|
||||
strncat(line2Buffer, b, 5);
|
||||
|
||||
for (int i = 12; i < 17; i++)
|
||||
{
|
||||
if (line2Buffer[i] == 0)
|
||||
line2Buffer[i] = ' ';
|
||||
}
|
||||
} // end of display IF
|
||||
else // step & Key Type display
|
||||
{
|
||||
//Step
|
||||
long tmpStep = arTuneStep[tuneStepIndex -1];
|
||||
|
||||
byte isStepKhz = 0;
|
||||
if (tmpStep >= 1000)
|
||||
{
|
||||
isStepKhz = 2;
|
||||
}
|
||||
|
||||
for (int i = 14; i >= 12 - isStepKhz; i--) {
|
||||
if (tmpStep > 0) {
|
||||
line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30;
|
||||
tmpStep /= 10;
|
||||
}
|
||||
else
|
||||
line2Buffer[i +isStepKhz] = ' ';
|
||||
}
|
||||
|
||||
if (isStepKhz == 0)
|
||||
{
|
||||
line2Buffer[15] = 'H';
|
||||
line2Buffer[16] = 'z';
|
||||
}
|
||||
}
|
||||
|
||||
line2Buffer[17] = ' ';
|
||||
|
||||
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
||||
if (cwKeyType == 0)
|
||||
{
|
||||
line2Buffer[18] = 'S';
|
||||
line2Buffer[19] = 'T';
|
||||
}
|
||||
else if (cwKeyType == 1)
|
||||
{
|
||||
line2Buffer[18] = 'I';
|
||||
line2Buffer[19] = 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
line2Buffer[18] = 'I';
|
||||
line2Buffer[19] = 'B';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//meterType : 0 = S.Meter, 1 : P.Meter
|
||||
void DisplayMeter(byte meterType, byte meterValue, char drawPosition)
|
||||
{
|
||||
if (meterType == 0 || meterType == 1 || meterType == 2)
|
||||
{
|
||||
drawMeter(meterValue);
|
||||
//int lineNumber = 0;
|
||||
//if ((displayOption1 & 0x01) == 0x01)
|
||||
//lineNumber = 1;
|
||||
|
||||
LCD_SetCursor(drawPosition, 2);
|
||||
LCD_Write('S');
|
||||
LCD_Write(':');
|
||||
for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6
|
||||
LCD_Write(lcdMeter[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//meterType : 0 = S.Meter, 1 = Forward Power Meter, 2 = SWR Meter
|
||||
void DisplayMeter(byte meterType, int meterValue, char drawPosition)
|
||||
{
|
||||
|
||||
#ifdef OPTION_SKINNYBARS //We want skinny meter bars with more text/numbers
|
||||
memcpy(&(line2Buffer[drawPosition]), " ", 8); //Blank that section of 8 characters first
|
||||
if (meterType == 0) { //SWR meter
|
||||
drawMeter(meterValue); //Only 2 characters
|
||||
line2Buffer[drawPosition] = 'S';
|
||||
byte sValue = round((float)meterValue * 1.5); //6 bars available only to show 9 S values
|
||||
sValue = sValue > 9 ? 9 : sValue; //Max S9
|
||||
line2Buffer[drawPosition + 1] = '0' + sValue; //0 to 9
|
||||
memcpy(&(line2Buffer[drawPosition + 2]), lcdMeter, 2); //Copy the S-Meter bars
|
||||
//Add the +10, +20, etc...
|
||||
if (meterValue > 6) {
|
||||
//We are over S9
|
||||
line2Buffer[drawPosition + 4] = '+';
|
||||
line2Buffer[drawPosition + 5] = '0' + meterValue - 6; //1,2,3 etc...
|
||||
line2Buffer[drawPosition + 6] = '0';
|
||||
}
|
||||
} else if (meterType == 1) { //Forward Power
|
||||
drawMeter(round((float)meterValue / 40)); //4 watts per bar
|
||||
//meterValue contains power value x 10 (one decimal point)
|
||||
line2Buffer[drawPosition] = 'P';
|
||||
meterValue = meterValue > 999 ? 999 : meterValue; //Limit to 99.9 watts!!!!
|
||||
//Remove decimal value and divide by 10
|
||||
meterValue = round((float)meterValue / 10);
|
||||
if (meterValue < 10) {
|
||||
line2Buffer[drawPosition + 1] = ' ';
|
||||
line2Buffer[drawPosition + 2] = '0' + meterValue; //0 to 9
|
||||
} else {
|
||||
line2Buffer[drawPosition + 1] = '0' + meterValue / 10;
|
||||
line2Buffer[drawPosition + 2] = '0' + (meterValue - ((meterValue / 10) * 10));
|
||||
}
|
||||
line2Buffer[drawPosition + 3] = 'W';
|
||||
memcpy(&(line2Buffer[drawPosition + 4]), lcdMeter, 2); //Copy the S-Meter bars
|
||||
} else { //SWR
|
||||
drawMeter((int)(((float)meterValue - 21) / 100)); //no bar = < 1.2, then 1 bar = 1.2 to 2.2, 2 bars = 2.2 to 3.2, etc...
|
||||
//meterValue contains SWR x 100 (two decimal point)
|
||||
memcpy(&(line2Buffer[drawPosition]), "SWR", 3);
|
||||
meterValue = round((float)meterValue / 10); //We now have swr x 10 (1 decimal point)
|
||||
if (meterValue < 100) { //10 to 99, no decimal point
|
||||
//Draw the decimal value
|
||||
line2Buffer[drawPosition + 3] = '0' + meterValue / 10;
|
||||
line2Buffer[drawPosition + 4] = '.';
|
||||
line2Buffer[drawPosition + 5] = '0' + (meterValue - ((meterValue / 10) * 10));
|
||||
} else {
|
||||
memcpy(&(line2Buffer[drawPosition + 3]), "10+", 3); //over 10
|
||||
}
|
||||
memcpy(&(line2Buffer[drawPosition + 6]), lcdMeter, 2); //Copy the S-Meter bars
|
||||
}
|
||||
#else //We want fat bars, easy to read, with less text/numbers
|
||||
//Serial.print("In displaymeter, meterValue: "); Serial.println(meterValue);
|
||||
drawMeter(meterValue);
|
||||
//Always line 2
|
||||
char sym = 'S';
|
||||
if (meterType == 1) sym = 'P';
|
||||
else if (meterType == 2) sym = 'R'; //For SWR
|
||||
line2Buffer[drawPosition] = sym;
|
||||
memcpy(&(line2Buffer[drawPosition + 1]), lcdMeter, 7);
|
||||
#endif //OPTION_SKINNYBARS
|
||||
|
||||
}
|
||||
|
||||
|
||||
byte testValue = 0;
|
||||
char checkCount = 0;
|
||||
|
||||
int currentSMeter = 0;
|
||||
//int sMeterLevels[] = {0, 5, 17, 41, 74, 140, 255, 365, 470};
|
||||
byte scaledSMeter = 0;
|
||||
char checkCountSMeter = 0;
|
||||
|
||||
//execute interval : 0.25sec
|
||||
void idle_process()
|
||||
{
|
||||
//space for user graphic display
|
||||
if (menuOn == 0)
|
||||
{
|
||||
if ((displayOption1 & 0x10) == 0x10) //always empty topline
|
||||
return;
|
||||
|
||||
//if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message
|
||||
if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) {
|
||||
if (checkCount++ > 1)
|
||||
{
|
||||
updateLine2Buffer(0); //call by scheduler
|
||||
printLine2(line2Buffer);
|
||||
line2DisplayStatus = 2;
|
||||
checkCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//EX for Meters
|
||||
/*
|
||||
DisplayMeter(0, testValue++, 0);
|
||||
if (testValue > 30)
|
||||
testValue = 0;
|
||||
*/
|
||||
|
||||
//Sample
|
||||
//DisplayMeter(0, analogRead(ANALOG_SMETER) / 30, 0);
|
||||
//DisplayMeter(0, analogRead(ANALOG_SMETER) / 10, 0);
|
||||
//delay_background(10, 0);
|
||||
//DisplayMeter(0, analogRead(ANALOG_SMETER), 0);
|
||||
//if (testValue > 30)
|
||||
// testValue = 0;
|
||||
|
||||
//S-Meter Display
|
||||
if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency))
|
||||
{
|
||||
int newSMeter;
|
||||
|
||||
//VK2ETA S-Meter from MAX9814 TC pin
|
||||
newSMeter = analogRead(ANALOG_SMETER);
|
||||
|
||||
//Faster attack, Slower release
|
||||
currentSMeter = (newSMeter > currentSMeter ? ((currentSMeter * 3 + newSMeter * 7) + 5) / 10 : ((currentSMeter * 7 + newSMeter * 3) + 5) / 10);
|
||||
|
||||
scaledSMeter = 0;
|
||||
for (byte s = 8; s >= 1; s--) {
|
||||
if (currentSMeter > sMeterLevels[s]) {
|
||||
scaledSMeter = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DisplayMeter(0, scaledSMeter, 0);
|
||||
checkCountSMeter = 0; //Reset Latency time
|
||||
} //end of S-Meter
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//AutoKey LCD Display Routine
|
||||
void Display_AutoKeyTextIndex(byte textIndex)
|
||||
{
|
||||
byte diplayAutoCWLine = 0;
|
||||
|
||||
if ((displayOption1 & 0x01) == 0x01)
|
||||
diplayAutoCWLine = 1;
|
||||
LCD_SetCursor(0, diplayAutoCWLine);
|
||||
LCD_Write(byteToChar(textIndex));
|
||||
LCD_Write(':');
|
||||
}
|
||||
|
||||
void DisplayCallsign(byte callSignLength)
|
||||
{
|
||||
printLineFromEEPRom(3, 20 - userCallsignLength, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT)
|
||||
}
|
||||
|
||||
void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo)
|
||||
{
|
||||
printLineF(3, fwVersionInfo);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,173 +0,0 @@
|
||||
/************************************************************************************
|
||||
* KD8CEC
|
||||
* kd8cec@gmail.com http://www.hamskey.com
|
||||
*
|
||||
* Merge two SI5351 Librarys
|
||||
* KE7ER's fixed vco and variable Clocks Configure values
|
||||
* G3ZIL's fixed Clock Configure Value and variable VCO
|
||||
* * I have combined the two libraries above. All licenses follow the above library.
|
||||
*
|
||||
* PLL-A is generated by fixing 850Mhz clock. All output clocks use PLL-A to
|
||||
* generate the frequency. This is the method used in QRP radios such as uBITX.
|
||||
* When switching to WSPR transmission mode, PLL-B operates for the base frequency to transmit WSPR.
|
||||
* The output clock channel that controls the frequency is connected to the PLL-B.
|
||||
* The WSPR protocol is generated by changing the clock of the PLL-B.
|
||||
************************************************************************************/
|
||||
|
||||
// ************* SI5315 routines - tks Jerry Gaffke, KE7ER ***********************
|
||||
// An minimalist standalone set of Si5351 routines.
|
||||
// VCOA is fixed at 875mhz, VCOB not used.
|
||||
// The output msynth dividers are used to generate 3 independent clocks
|
||||
// with 1hz resolution to any frequency between 4khz and 109mhz.
|
||||
|
||||
// Usage:
|
||||
// Call si5351bx_init() once at startup with no args;
|
||||
// Call si5351bx_setfreq(clknum, freq) each time one of the
|
||||
// three output CLK pins is to be updated to a new frequency.
|
||||
// A freq of 0 serves to shut down that output clock.
|
||||
|
||||
// The global variable si5351bx_vcoa starts out equal to the nominal VCOA
|
||||
// frequency of 25mhz*35 = 875000000 Hz. To correct for 25mhz crystal errors,
|
||||
// the user can adjust this value. The vco frequency will not change but
|
||||
// the number used for the (a+b/c) output msynth calculations is affected.
|
||||
// Example: We call for a 5mhz signal, but it measures to be 5.001mhz.
|
||||
// So the actual vcoa frequency is 875mhz*5.001/5.000 = 875175000 Hz,
|
||||
// To correct for this error: si5351bx_vcoa=875175000;
|
||||
|
||||
// Most users will never need to generate clocks below 500khz.
|
||||
// But it is possible to do so by loading a value between 0 and 7 into
|
||||
// the global variable si5351bx_rdiv, be sure to return it to a value of 0
|
||||
// before setting some other CLK output pin. The affected clock will be
|
||||
// divided down by a power of two defined by 2**si5351_rdiv
|
||||
// A value of zero gives a divide factor of 1, a value of 7 divides by 128.
|
||||
// This lightweight method is a reasonable compromise for a seldom used feature.
|
||||
|
||||
|
||||
#define BB0(x) ((uint8_t)x) // Bust int32 into Bytes
|
||||
#define BB1(x) ((uint8_t)(x>>8))
|
||||
#define BB2(x) ((uint8_t)(x>>16))
|
||||
|
||||
#define SI5351BX_ADDR 0x60 // I2C address of Si5351 (typical)
|
||||
#define SI5351BX_XTALPF 2 // 1:6pf 2:8pf 3:10pf
|
||||
|
||||
// If using 27mhz crystal, set XTAL=27000000, MSA=33. Then vco=891mhz
|
||||
#define SI5351BX_XTAL 25000000 // Crystal freq in Hz
|
||||
#define SI5351BX_MSA 35 // VCOA is at 25mhz*35 = 875mhz
|
||||
|
||||
// User program may have reason to poke new values into these 3 RAM variables
|
||||
uint32_t si5351bx_vcoa = (SI5351BX_XTAL*SI5351BX_MSA); // 25mhzXtal calibrate
|
||||
uint8_t si5351bx_rdiv = 0; // 0-7, CLK pin sees fout/(2**rdiv)
|
||||
uint8_t si5351bx_drive[3] = {1, 1, 1}; // 0=2ma 1=4ma 2=6ma 3=8ma for CLK 0,1,2
|
||||
uint8_t si5351bx_clken = 0xFF; // Private, all CLK output drivers off
|
||||
int32_t calibration = 0;
|
||||
|
||||
void i2cWrite(uint8_t reg, uint8_t val) { // write reg via i2c
|
||||
Wire.beginTransmission(SI5351BX_ADDR);
|
||||
Wire.write(reg);
|
||||
Wire.write(val);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void i2cWriten(uint8_t reg, uint8_t *vals, uint8_t vcnt) { // write array
|
||||
Wire.beginTransmission(SI5351BX_ADDR);
|
||||
Wire.write(reg);
|
||||
while (vcnt--) Wire.write(*vals++);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t si5351Val[8] = {0, 1, 0, 0, 0, 0, 0, 0}; //for reduce program memory size
|
||||
|
||||
void si5351bx_init() { // Call once at power-up, start PLLA
|
||||
uint32_t msxp1;
|
||||
Wire.begin();
|
||||
i2cWrite(149, 0); // SpreadSpectrum off
|
||||
i2cWrite(3, si5351bx_clken); // Disable all CLK output drivers
|
||||
i2cWrite(183, SI5351BX_XTALPF << 6); // Set 25mhz crystal load capacitance
|
||||
msxp1 = 128 * SI5351BX_MSA - 512; // and msxp2=0, msxp3=1, not fractional
|
||||
//uint8_t vals[8] = {0, 1, BB2(msxp1), BB1(msxp1), BB0(msxp1), 0, 0, 0};
|
||||
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)
|
||||
}
|
||||
|
||||
void si5351bx_setfreq(uint8_t clknum, uint32_t fout) { // Set a CLK to fout Hz
|
||||
uint32_t msa, msb, msc, msxp1, msxp2, msxp3p2top;
|
||||
if ((fout < 500000) || (fout > 109000000)) // If clock freq out of range
|
||||
si5351bx_clken |= 1 << clknum; // shut down the clock
|
||||
else {
|
||||
msa = si5351bx_vcoa / fout; // Integer part of vco/fout
|
||||
msb = si5351bx_vcoa % fout; // Fractional part of vco/fout
|
||||
msc = fout; // Divide by 2 till fits in reg
|
||||
while (msc & 0xfff00000) {
|
||||
msb = msb >> 1;
|
||||
msc = msc >> 1;
|
||||
}
|
||||
msxp1 = (128 * msa + 128 * msb / msc - 512) | (((uint32_t)si5351bx_rdiv) << 20);
|
||||
msxp2 = 128 * msb - 128 * msb / msc * msc; // msxp3 == msc;
|
||||
msxp3p2top = (((msc & 0x0F0000) << 4) | msxp2); // 2 top nibbles
|
||||
uint8_t vals[8] = { BB1(msc), BB0(msc), BB2(msxp1), BB1(msxp1),
|
||||
BB0(msxp1), BB2(msxp3p2top), BB1(msxp2), BB0(msxp2)
|
||||
};
|
||||
i2cWriten(42 + (clknum * 8), vals, 8); // Write to 8 msynth regs
|
||||
i2cWrite(16 + clknum, 0x0C | si5351bx_drive[clknum]); // use local msynth
|
||||
si5351bx_clken &= ~(1 << clknum); // Clear bit to enable clock
|
||||
}
|
||||
i2cWrite(3, si5351bx_clken); // Enable/disable clock
|
||||
}
|
||||
|
||||
void si5351_set_calibration(int32_t cal){
|
||||
si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + cal; // apply the calibration correction factor
|
||||
si5351bx_setfreq(0, usbCarrier);
|
||||
}
|
||||
|
||||
void SetCarrierFreq()
|
||||
{
|
||||
unsigned long appliedCarrier = ((cwMode == 0 ? usbCarrier : cwmCarrier) + (isIFShift && (inTx == 0) ? ifShiftValue : 0));
|
||||
//si5351bx_setfreq(0, (sdrModeOn ? 0 : appliedCarrier));
|
||||
si5351bx_setfreq(0, ((sdrModeOn && (inTx == 0)) ? 0 : appliedCarrier)); //found bug by KG4GEK
|
||||
|
||||
|
||||
/*
|
||||
if (cwMode == 0)
|
||||
si5351bx_setfreq(0, usbCarrier + (isIFShift ? ifShiftValue : 0));
|
||||
else
|
||||
si5351bx_setfreq(0, cwmCarrier + (isIFShift ? ifShiftValue : 0));
|
||||
*/
|
||||
}
|
||||
|
||||
void initOscillators(){
|
||||
//initialize the SI5351
|
||||
si5351bx_init();
|
||||
si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + calibration; // apply the calibration correction factor
|
||||
SetCarrierFreq();
|
||||
}
|
||||
|
||||
//============================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,259 +0,0 @@
|
||||
/**
|
||||
* The user interface of the ubitx consists of the encoder, the push-button on top of it
|
||||
* and the 16x2 LCD display.
|
||||
* The upper line of the display is constantly used to display frequency and status
|
||||
* of the radio. Occasionally, it is used to provide a two-line information that is
|
||||
* quickly cleared up.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
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
|
||||
};
|
||||
*/
|
||||
|
||||
//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA
|
||||
|
||||
#ifdef OPTION_SKINNYBARS //We want skninny bars with more text
|
||||
//VK2ETA modded "Skinny" bitmaps
|
||||
const PROGMEM uint8_t meters_bitmap[] = {
|
||||
// B01110, B10001, B10001, B11111, B11011, B11011, B11111, B00000, //Padlock Symbol, for merging. Not working, see below
|
||||
B00000, B00000, B00000, B00000, B00000, B00000, B00000, B10000, //shortest bar
|
||||
B00000, B00000, B00000, B00000, B00000, B00000, B00100, B10100,
|
||||
B00000, B00000, B00000, B00000, B00000, B00001, B00101, B10101,
|
||||
B00000, B00000, B00000, B00000, B10000, B10000, B10000, B10000,
|
||||
B00000, B00000, B00000, B00100, B10100, B10100, B10100, B10100,
|
||||
B00000, B00000, B00001, B00101, B10101, B10101, B10101, B10101, //tallest bar
|
||||
B00000, B00010, B00111, B00010, B01000, B11100, B01000, B00000, // ++ sign
|
||||
};
|
||||
#else
|
||||
//VK2ETA "Fat" bars, easy to read, with less text
|
||||
const PROGMEM uint8_t meters_bitmap[] = {
|
||||
// B01110, B10001, B10001, B11111, B11011, B11011, B11111, B00000, //Padlock Symbol, for merging. Not working, see below
|
||||
B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111, //shortest bar
|
||||
B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111,
|
||||
B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111,
|
||||
B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111,
|
||||
B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111,
|
||||
B00000, B00000, B11111, B11111, B11111, B11111, B11111, B11111, //tallest bar
|
||||
B00000, B00010, B00111, B00010, B01000, B11100, B01000, B00000, // ++ sign
|
||||
};
|
||||
#endif //OPTION_SKINNYBARS
|
||||
PGM_P p_metes_bitmap = reinterpret_cast<PGM_P>(meters_bitmap);
|
||||
|
||||
const PROGMEM uint8_t lock_bitmap[8] = {
|
||||
0b01110,
|
||||
0b10001,
|
||||
0b10001,
|
||||
0b11111,
|
||||
0b11011,
|
||||
0b11011,
|
||||
0b11111,
|
||||
0b00000};
|
||||
PGM_P plock_bitmap = reinterpret_cast<PGM_P>(lock_bitmap);
|
||||
|
||||
|
||||
// initializes the custom characters
|
||||
// we start from char 1 as char 0 terminates the string!
|
||||
void initMeter(){
|
||||
uint8_t tmpbytes[8];
|
||||
byte i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(plock_bitmap + i);
|
||||
LCD_CreateChar(0, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i);
|
||||
LCD_CreateChar(1, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8);
|
||||
LCD_CreateChar(2, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16);
|
||||
LCD_CreateChar(3, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24);
|
||||
LCD_CreateChar(4, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32);
|
||||
LCD_CreateChar(5, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40);
|
||||
LCD_CreateChar(6, tmpbytes);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 48);
|
||||
LCD_CreateChar(6, tmpbytes);
|
||||
}
|
||||
|
||||
|
||||
//by KD8CEC
|
||||
//0 ~ 25 : 30 over : + 10
|
||||
/*
|
||||
void drawMeter(int needle) {
|
||||
//5Char + O over
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (needle >= 5)
|
||||
lcdMeter[i] = 5; //full
|
||||
else if (needle > 0)
|
||||
lcdMeter[i] = needle; //full
|
||||
else //0
|
||||
lcdMeter[i] = 0x20;
|
||||
|
||||
needle -= 5;
|
||||
}
|
||||
|
||||
if (needle > 0)
|
||||
lcdMeter[5] = 6;
|
||||
else
|
||||
lcdMeter[5] = 0x20;
|
||||
}
|
||||
*/
|
||||
//VK2ETA meter for S.Meter, power and SWR
|
||||
void drawMeter(int needle)
|
||||
{
|
||||
#ifdef OPTION_SKINNYBARS
|
||||
//Fill buffer with growing set of bars, up to needle value
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (needle > i)
|
||||
lcdMeter[i / 3] = byte(i + 1); //Custom characters above
|
||||
else if (i == 1 || i == 4) {
|
||||
lcdMeter[i / 3] = 0x20; //blank
|
||||
}
|
||||
}
|
||||
#else //Must be "fat" bars
|
||||
//Fill buffer with growing set of bars, up to needle value
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (needle > i)
|
||||
lcdMeter[i] = byte(i + 1); //Custom characters above
|
||||
else
|
||||
lcdMeter[i] = 0x20; //blank
|
||||
}
|
||||
if (needle > 7) {
|
||||
lcdMeter[6] = byte(7); //Custom character "++"
|
||||
} else if (needle > 6) {
|
||||
lcdMeter[6] = 0x2B; //"+"
|
||||
} else lcdMeter[6] = 0x20;
|
||||
#endif //OPTION_FATBARS
|
||||
}
|
||||
|
||||
|
||||
|
||||
char byteToChar(byte srcByte){
|
||||
if (srcByte < 10)
|
||||
return 0x30 + srcByte;
|
||||
else
|
||||
return 'A' + srcByte - 10;
|
||||
}
|
||||
|
||||
//returns true if the button is pressed
|
||||
int btnDown(void){
|
||||
#ifdef EXTEND_KEY_GROUP1
|
||||
if (analogRead(FBUTTON) > FUNCTION_KEY_ADC)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
|
||||
#else
|
||||
if (digitalRead(FBUTTON) == HIGH)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef EXTEND_KEY_GROUP1
|
||||
int getBtnStatus(void){
|
||||
int readButtonValue = analogRead(FBUTTON);
|
||||
|
||||
if (analogRead(FBUTTON) < FUNCTION_KEY_ADC)
|
||||
return FKEY_PRESS;
|
||||
else
|
||||
{
|
||||
readButtonValue = readButtonValue / 4;
|
||||
//return FKEY_VFOCHANGE;
|
||||
for (int i = 0; i < 16; i++)
|
||||
if (KeyValues[i][0] <= readButtonValue && KeyValues[i][1] >= readButtonValue)
|
||||
return KeyValues[i][2];
|
||||
//return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int enc_prev_state = 3;
|
||||
|
||||
/**
|
||||
* The A7 And A6 are purely analog lines on the Arduino Nano
|
||||
* These need to be pulled up externally using two 10 K resistors
|
||||
*
|
||||
* There are excellent pages on the Internet about how these encoders work
|
||||
* and how they should be used. We have elected to use the simplest way
|
||||
* to use these encoders without the complexity of interrupts etc to
|
||||
* keep it understandable.
|
||||
*
|
||||
* The enc_state returns a two-bit number such that each bit reflects the current
|
||||
* value of each of the two phases of the encoder
|
||||
*
|
||||
* The enc_read returns the number of net pulses counted over 50 msecs.
|
||||
* If the puluses are -ve, they were anti-clockwise, if they are +ve, the
|
||||
* were in the clockwise directions. Higher the pulses, greater the speed
|
||||
* at which the enccoder was spun
|
||||
*/
|
||||
|
||||
byte enc_state (void) {
|
||||
return (analogRead(ENC_A) > 500 ? 1 : 0) + (analogRead(ENC_B) > 500 ? 2: 0);
|
||||
}
|
||||
|
||||
int enc_read(void) {
|
||||
int result = 0;
|
||||
byte newState;
|
||||
int enc_speed = 0;
|
||||
|
||||
unsigned long start_at = millis();
|
||||
|
||||
while (millis() - start_at < 50) { // check if the previous state was stable
|
||||
newState = enc_state(); // Get current state
|
||||
|
||||
if (newState != enc_prev_state)
|
||||
delay (1);
|
||||
|
||||
if (enc_state() != newState || newState == enc_prev_state)
|
||||
continue;
|
||||
//these transitions point to the encoder being rotated anti-clockwise
|
||||
if ((enc_prev_state == 0 && newState == 2) ||
|
||||
(enc_prev_state == 2 && newState == 3) ||
|
||||
(enc_prev_state == 3 && newState == 1) ||
|
||||
(enc_prev_state == 1 && newState == 0)){
|
||||
result--;
|
||||
}
|
||||
//these transitions point o the enccoder being rotated clockwise
|
||||
if ((enc_prev_state == 0 && newState == 1) ||
|
||||
(enc_prev_state == 1 && newState == 3) ||
|
||||
(enc_prev_state == 3 && newState == 2) ||
|
||||
(enc_prev_state == 2 && newState == 0)){
|
||||
result++;
|
||||
}
|
||||
enc_prev_state = newState; // Record state for next pulse interpretation
|
||||
enc_speed++;
|
||||
delay(1);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
/**********************************************************************************
|
||||
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 <EEPROM.h>
|
||||
#include "ubitx.h"
|
||||
|
||||
//begin of test
|
||||
byte WsprToneCode[164];
|
||||
|
||||
unsigned 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 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;
|
||||
byte 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
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 71 KiB |
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user