Compare commits

...

9 Commits

Author SHA1 Message Date
phdlee
a49d5e85b8 line2 display sample1 2018-01-29 22:49:30 +09:00
phdlee
282c196f63 fixed cw adc range bug 2018-01-29 18:38:48 +09:00
phdlee
ee23827def rename version to 0.30 2018-01-27 18:38:18 +09:00
phdlee
8d4c788e11 1st Test new CW Keyer and add cat message processing 2018-01-27 18:05:08 +09:00
phdlee
cc7dd752e6 add function adjust CW ADC Range 2018-01-27 16:39:54 +09:00
phdlee
4506ff1c1b for Reduce CW Keying error 2018-01-26 21:47:15 +09:00
phdlee
db543c43e1 Add Comment 2018-01-26 18:23:52 +09:00
phdlee
981db341db change defautl key type 2018-01-25 23:31:47 +09:00
phdlee
020b34e504 add menu for new Keyer logic 2018-01-25 23:15:24 +09:00
8 changed files with 637 additions and 195 deletions

View File

@@ -1,4 +1,5 @@
/*************************************************************************
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
@@ -471,7 +472,7 @@ void WriteEEPRom_FT817(byte fromType)
printLineF2(F("Sidetone set! CAT"));
EEPROM.put(CW_SIDETONE, sideTone);
delay(300); //If timeout errors occur in the calling software, remove them
printLine2(""); //Ham radio deluxe is the only one that supports this feature yet. and ham radio deluxe has wait time as greater than 500ms
clearLine2();
}
break;
@@ -483,7 +484,8 @@ void WriteEEPRom_FT817(byte fromType)
printLineF2(F("Sidetone set! CAT"));
EEPROM.put(CW_SIDETONE, sideTone);
delay(300); //If timeout errors occur in the calling software, remove them
printLine2(""); //Ham radio deluxe is the only one that supports this feature yet. and ham radio deluxe has wait time as greater than 500ms
clearLine2();
line2DisplayStatus = 0;
}
break;
@@ -503,7 +505,7 @@ void WriteEEPRom_FT817(byte fromType)
printLineF2(F("CW Speed set!"));
EEPROM.put(CW_DELAY, cwDelayTime);
delay(300);
printLine2("");
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)
@@ -512,7 +514,7 @@ void WriteEEPRom_FT817(byte fromType)
printLineF2(F("CW Speed set!"));
EEPROM.put(CW_SPEED, cwSpeed);
delay(300);
printLine2("");
clearLine2();
break;
/*

View File

@@ -1,4 +1,6 @@
/*************************************************************************
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
@@ -13,6 +15,7 @@
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
@@ -295,8 +298,12 @@ void controlAutoCW(){
}
printLineFromEEPRom(0, 2, cwStartIndex + displayScrolStep + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ);
byte diplayAutoCWLine = 0;
if ((displayOption1 & 0x01) == 0x01)
diplayAutoCWLine = 1;
lcd.setCursor(0,0);
lcd.setCursor(0, diplayAutoCWLine);
lcd.write(byteToChar(selectedCWTextIndex));
lcd.write(':');
isNeedScroll = (cwEndIndex - cwStartIndex) > 14 ? 1 : 0;

View File

@@ -1,4 +1,10 @@
/**
Since KD8CEC Version 0.29, most of the original code is no longer available.
Most features(TX, Frequency Range, Ham Band, TX Control, CW delay, start Delay... more) have been added by KD8CEC.
However, the license rules are subject to the original source rules.
DE Ian KD8CEC
Original source comment -------------------------------------------------------------
* This source file is under General Public License version 3.
*
* This verision uses a built-in Si5351 library
@@ -78,6 +84,7 @@
#define PTT (A3)
#define ANALOG_KEYER (A6)
#define ANALOG_SPARE (A7)
#define ANALOG_SMETER (A7) //by KD8CEC
/**
* The Raduino board is the size of a standard 16x2 LCD panel. It has three connectors:
@@ -152,7 +159,24 @@ int count = 0; //to generally count ticks, loops, etc
#define TX_TUNE_TYPE 261 //
#define HAM_BAND_RANGE 262 //FROM (2BYTE) TO (2BYTE) * 10 = 40byte
#define HAM_BAND_FREQS 302 //40, 1 BAND = 4Byte most bit is mode
#define TUNING_STEP 342 //TUNING STEP * 6 (index 1 + STEPS 5)
#define TUNING_STEP 342 //TUNING STEP * 6 (index 1 + STEPS 5)
//for reduce cw key error, eeprom address
#define CW_ADC_MOST_BIT1 348 //most 2bits of DOT_TO , DOT_FROM, ST_TO, ST_FROM
#define CW_ADC_ST_FROM 349 //CW ADC Range STRAIGHT KEY from (Lower 8 bit)
#define CW_ADC_ST_TO 350 //CW ADC Range STRAIGHT KEY to (Lower 8 bit)
#define CW_ADC_DOT_FROM 351 //CW ADC Range DOT from (Lower 8 bit)
#define CW_ADC_DOT_TO 352 //CW ADC Range DOT to (Lower 8 bit)
#define CW_ADC_MOST_BIT2 353 //most 2bits of BOTH_TO, BOTH_FROM, DASH_TO, DASH_FROM
#define CW_ADC_DASH_FROM 354 //CW ADC Range DASH from (Lower 8 bit)
#define CW_ADC_DASH_TO 355 //CW ADC Range DASH to (Lower 8 bit)
#define CW_ADC_BOTH_FROM 356 //CW ADC Range BOTH from (Lower 8 bit)
#define CW_ADC_BOTH_TO 357 //CW ADC Range BOTH to (Lower 8 bit)
#define CW_KEY_TYPE 358
#define DISPLAY_OPTION1 361 //Display Option1
#define DISPLAY_OPTION2 362 //Display Option2
//Check Firmware type and version
#define FIRMWAR_ID_ADDR 776 //776 : 0x59, 777 :0x58, 778 : 0x68 : Id Number, if not found id, erase eeprom(32~1023) for prevent system error.
@@ -239,6 +263,23 @@ byte isTxType = 0; //000000[0 - isSplit] [0 - isTXStop]
byte arTuneStep[5];
byte tuneStepIndex; //default Value 0, start Offset is 0 because of check new user
byte displayOption1 = 0;
byte displayOption2 = 0;
//CW ADC Range
int cwAdcSTFrom = 0;
int cwAdcSTTo = 0;
int cwAdcDotFrom = 0;
int cwAdcDotTo = 0;
int cwAdcDashFrom = 0;
int cwAdcDashTo = 0;
int cwAdcBothFrom = 0;
int cwAdcBothTo = 0;
byte cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
bool Iambic_Key = true;
#define IAMBICB 0x10 // 0 for Iambic A, 1 for Iambic B
unsigned char keyerControl = IAMBICB;
//Variables for auto cw mode
byte isCWAutoMode = 0; //0 : none, 1 : CW_AutoMode_Menu_Selection, 2 : CW_AutoMode Sending
byte cwAutoTextCount = 0; //cwAutoText Count
@@ -267,6 +308,10 @@ unsigned long dbgCount = 0; //not used now
unsigned char txFilter = 0; //which of the four transmit filters are in use
boolean modeCalibrate = false;//this mode of menus shows extended menus to calibrate the oscillators and choose the proper
//beat frequency
unsigned long beforeIdle_ProcessTime = 0; //for check Idle time
byte line2DisplayStatus = 0; //0:Clear, 1 : menu, 1: DisplayFrom Idle,
/**
* Below are the basic functions that control the uBitx. Understanding the functions before
* you start hacking around
@@ -334,7 +379,6 @@ void saveBandFreqByIndex(unsigned long f, unsigned long mode, char bandIndex) {
EEPROM.put(HAM_BAND_FREQS + 4 * bandIndex, (f & 0x3FFFFFFF) | (mode << 30) );
}
/*
KD8CEC
When using the basic delay of the Arduino, the program freezes.
@@ -568,8 +612,13 @@ applied Threshold for reduct errors, dial Lock, dynamic Step
byte threshold = 2; //noe action for count
unsigned long lastEncInputtime = 0;
int encodedSumValue = 0;
unsigned long lastTunetime = 0; //if continous moving, skip threshold processing
byte lastMovedirection = 0; //0 : stop, 1 : cw, 2 : ccw
#define skipThresholdTime 100
#define encodeTimeOut 1000
void doTuning(){
void doTuningWithThresHold(){
int s = 0;
unsigned long prev_freq;
long incdecValue = 0;
@@ -586,6 +635,8 @@ void doTuning(){
if (s == 0) {
if (encodedSumValue != 0 && (millis() - encodeTimeOut) > lastEncInputtime)
encodedSumValue = 0;
lastMovedirection = 0;
return;
}
lastEncInputtime = millis();
@@ -593,23 +644,25 @@ void doTuning(){
//for check moving direction
encodedSumValue += (s > 0 ? 1 : -1);
//check threshold
if ((encodedSumValue * encodedSumValue) <= (threshold * threshold))
//check threshold and operator actions (hold dial speed = continous moving, skip threshold check)
if ((lastTunetime < millis() - skipThresholdTime) && ((encodedSumValue * encodedSumValue) <= (threshold * threshold)))
return;
lastTunetime = millis();
//Valid Action without noise
encodedSumValue = 0;
prev_freq = frequency;
//incdecValue = tuningStep * s;
frequency += (arTuneStep[tuneStepIndex -1] * s);
frequency += (arTuneStep[tuneStepIndex -1] * s * (s * s < 10 ? 1 : 3)); //appield weight (s is speed)
if (prev_freq < 10000000l && frequency > 10000000l)
isUSB = true;
if (prev_freq > 10000000l && frequency < 10000000l)
isUSB = false;
setFrequency(frequency);
updateDisplay();
}
@@ -680,7 +733,10 @@ void initSettings(){
EEPROM.get(VFO_B, vfoB);
EEPROM.get(CW_SIDETONE, sideTone);
EEPROM.get(CW_SPEED, cwSpeed);
//End of original code
//----------------------------------------------------------------
//Add Lines by KD8CEC
//for custom source Section =============================
//ID & Version Check from EEProm
//if found different firmware, erase eeprom (32
@@ -715,6 +771,24 @@ void initSettings(){
//CW interval between TX and CW Start
EEPROM.get(CW_START, delayBeforeCWStartTime);
EEPROM.get(CW_KEY_TYPE, cwKeyType);
if (cwKeyType > 2)
cwKeyType = 0;
if (cwKeyType == 0)
Iambic_Key = false;
else
{
Iambic_Key = true;
if (cwKeyType = 1)
keyerControl &= ~IAMBICB;
else
keyerControl |= IAMBICB;
}
EEPROM.get(DISPLAY_OPTION1, displayOption1);
EEPROM.get(DISPLAY_OPTION2, displayOption2);
//User callsign information
if (EEPROM.read(USER_CALLSIGN_KEY) == 0x59)
@@ -749,7 +823,7 @@ void initSettings(){
hamBandRange[0][0] = 1810; hamBandRange[0][1] = 2000;
hamBandRange[1][0] = 3500; hamBandRange[1][1] = 3800;
hamBandRange[2][0] = 5351; hamBandRange[2][1] = 5367;
hamBandRange[3][0] = 7000; hamBandRange[3][1] = 7200;
hamBandRange[3][0] = 7000; hamBandRange[3][1] = 7300; //region 1
hamBandRange[4][0] = 10100; hamBandRange[4][1] = 10150;
hamBandRange[5][0] = 14000; hamBandRange[5][1] = 14350;
hamBandRange[6][0] = 18068; hamBandRange[6][1] = 18168;
@@ -781,8 +855,47 @@ void initSettings(){
if (tuneStepIndex == 0) //New User
tuneStepIndex = 3;
//CW Key ADC Range ======= adjust set value for reduce cw keying error
//by KD8CEC
unsigned int tmpMostBits = 0;
tmpMostBits = EEPROM.read(CW_ADC_MOST_BIT1);
cwAdcSTFrom = EEPROM.read(CW_ADC_ST_FROM) | ((tmpMostBits & 0x03) << 8);
cwAdcSTTo = EEPROM.read(CW_ADC_ST_TO) | ((tmpMostBits & 0x0C) << 6);
cwAdcDotFrom = EEPROM.read(CW_ADC_DOT_FROM) | ((tmpMostBits & 0x30) << 4);
cwAdcDotTo = EEPROM.read(CW_ADC_DOT_TO) | ((tmpMostBits & 0xC0) << 2);
tmpMostBits = EEPROM.read(CW_ADC_MOST_BIT2);
cwAdcDashFrom = EEPROM.read(CW_ADC_DASH_FROM) | ((tmpMostBits & 0x03) << 8);
cwAdcDashTo = EEPROM.read(CW_ADC_DASH_TO) | ((tmpMostBits & 0x0C) << 6);
cwAdcBothFrom = EEPROM.read(CW_ADC_BOTH_FROM) | ((tmpMostBits & 0x30) << 4);
cwAdcBothTo = EEPROM.read(CW_ADC_BOTH_TO) | ((tmpMostBits & 0xC0) << 2);
//default Value (for original hardware)
if (cwAdcSTFrom >= cwAdcSTTo)
{
cwAdcSTFrom = 0;
cwAdcSTTo = 50;
}
if (cwAdcBothFrom >= cwAdcBothTo)
{
cwAdcBothFrom = 51;
cwAdcBothTo = 300;
}
if (cwAdcDotFrom >= cwAdcDotTo)
{
cwAdcDotFrom = 301;
cwAdcDotTo = 600;
}
if (cwAdcDashFrom >= cwAdcDashTo)
{
cwAdcDashFrom = 601;
cwAdcDashTo = 800;
}
//end of CW Keying Variables
if (cwDelayTime < 1 || cwDelayTime > 250)
cwDelayTime = 60;
@@ -792,6 +905,7 @@ void initSettings(){
if (vfoB_mode < 2)
vfoB_mode = 3;
//original code with modified by kd8cec
if (usbCarrier > 12010000l || usbCarrier < 11990000l)
usbCarrier = 11995000l;
@@ -804,8 +918,9 @@ void initSettings(){
vfoB = 14150000l;
vfoB_mode = 3;
}
//end of original code section
//for protect eeprom life
//for protect eeprom life by KD8CEC
vfoA_eeprom = vfoA;
vfoB_eeprom = vfoB;
vfoA_mode_eeprom = vfoA_mode;
@@ -841,6 +956,7 @@ void initPorts(){
pinMode(PTT, INPUT_PULLUP);
pinMode(ANALOG_KEYER, INPUT_PULLUP);
pinMode(ANALOG_SMETER, INPUT); //by KD8CEC
pinMode(CW_TONE, OUTPUT);
digitalWrite(CW_TONE, 0);
@@ -876,7 +992,7 @@ void setup()
//Serial.begin(9600);
lcd.begin(16, 2);
printLineF(1, F("CECBT v0.27"));
printLineF(1, F("CECBT v0.31"));
Init_Cat(38400, SERIAL_8N1);
initMeter(); //not used in this build
@@ -890,7 +1006,7 @@ void setup()
else {
printLineF(0, F("uBITX v0.20"));
delay(500);
printLine2("");
clearLine2();
}
initPorts();
@@ -963,8 +1079,13 @@ void loop(){
if (ritOn)
doRIT();
else
doTuning();
}
doTuningWithThresHold();
if (isCWAutoMode == 0 && beforeIdle_ProcessTime < millis() - 500) {
idle_process();
beforeIdle_ProcessTime = millis();
}
} //end of check TX Status
//we check CAT after the encoder as it might put the radio into TX
Check_Cat(inTx? 1 : 0);

View File

@@ -14,6 +14,7 @@ void btnWaitForClick(){
void factory_alignment(){
factoryCalibration(1);
line2DisplayStatus = 1;
if (calibration == 0){
printLine2("Setup Aborted");

131
ubitx_20/ubitx_idle.ino Normal file
View File

@@ -0,0 +1,131 @@
/*************************************************************************
KD8CEC's uBITX Idle time Processing
Functions that run at times that do not affect TX, CW, and CAT
It is called in 1/10 time unit.
-----------------------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
byte line2Buffer[17];
//KD8CEC 200Hz ST
//L14.150 200Hz ST
//U14.150 +150khz
//Example Line2 Optinal Display
void updateLine2Buffer()
{
unsigned long tmpFreq = 0;
if (ritOn)
{
line2Buffer[0] = 'R';
line2Buffer[1] = 'i';
line2Buffer[2] = 't';
line2Buffer[3] = 'T';
line2Buffer[4] = 'X';
line2Buffer[5] = ':';
//display frequency
tmpFreq = ritTxFrequency;
for (int i = 15; i >= 6; i--) {
if (tmpFreq > 0) {
if (i == 12 || i == 8) line2Buffer[i] = '.';
else {
line2Buffer[i] = tmpFreq % 10 + 0x30;
tmpFreq /= 10;
}
}
else
line2Buffer[i] = ' ';
}
return;
}
if (vfoActive == VFO_B)
{
tmpFreq = vfoA;
//line2Buffer[0] = 'A';
}
else
{
tmpFreq = vfoB;
//line2Buffer[0] = 'B';
}
//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] = ' ';
}
line2Buffer[6] = 'k';
line2Buffer[7] = ' ';
//Step
byte tmpStep = arTuneStep[tuneStepIndex -1];
for (int i = 10; i >= 8; i--) {
if (tmpStep > 0) {
line2Buffer[i] = tmpStep % 10 + 0x30;
tmpStep /= 10;
}
else
line2Buffer[i] = ' ';
}
line2Buffer[11] = 'H';
line2Buffer[12] = 'z';
line2Buffer[13] = ' ';
//if (
//Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
if (cwKeyType == 0)
{
line2Buffer[14] = 'S';
line2Buffer[15] = 'T';
}
else if (cwKeyType == 1)
{
line2Buffer[14] = 'I';
line2Buffer[15] = 'A';
}
else
{
line2Buffer[14] = 'I';
line2Buffer[15] = 'B';
}
}
void idle_process()
{
//space for user graphic display
if (menuOn == 0)
{
//if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message
//if (line2DisplayStatus == 0) {
updateLine2Buffer();
printLine2(line2Buffer);
line2DisplayStatus = 2;
//}
}
}

View File

@@ -1,8 +1,9 @@
/**
* CW Keyer
* CW Key logic change with ron's code (ubitx_keyer.cpp) <=== **********************************
* The file you are working on. The code only applies and is still in testing. <==== ***********
*
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.
@@ -82,204 +83,167 @@ void cwKeyUp(){
cwTimeout = millis() + cwDelayTime * 10;
}
/*****************************************************************************
// New logic, by RON
// modified by KD8CEC
******************************************************************************/
//Variables for Ron's new logic
#define DIT_L 0x01 // DIT latch
#define DAH_L 0x02 // DAH latch
#define DIT_PROC 0x04 // DIT is being processed
#define PDLSWAP 0x08 // 0 for normal, 1 for swap
#define IAMBICB 0x10 // 0 for Iambic A, 1 for Iambic B
enum KSTYPE {IDLE, CHK_DIT, CHK_DAH, KEYED_PREP, KEYED, INTER_ELEMENT };
static long ktimer;
bool Iambic_Key = true;
unsigned char keyerControl = IAMBICB;
unsigned char keyerState = IDLE;
//Below is a test to reduce the keying error.
/*
char update_PaddleLatch(byte isUpdateKeyState) {
int paddle = analogRead(ANALOG_KEYER);
unsigned char tmpKeyerControl;
if (paddle > 800) // above 4v is up
tmpKeyerControl = 0;
//else if (paddle > 600) // 4-3v is DASH
else if (paddle > 693 && paddle < 700) // 4-3v is DASH
tmpKeyerControl |= DAH_L;
//else if (paddle > 300) //1-2v is DOT
else if (paddle > 323 && paddle < 328) //1-2v is DOT
tmpKeyerControl |= DIT_L;
//else if (paddle > 50)
else if (paddle > 280 && paddle < 290)
tmpKeyerControl |= (DAH_L | DIT_L) ; //both are between 1 and 2v
else
tmpKeyerControl = 0 ; //STRAIGHT KEY in original code
//keyerControl |= (DAH_L | DIT_L) ; //STRAIGHT KEY in original code
if (isUpdateKeyState == 1) {
keyerControl |= tmpKeyerControl;
}
byte buff[17];
sprintf(buff, "Key : %d", paddle);
if (tmpKeyerControl > 0)
printLine2(buff);
return tmpKeyerControl;
//if (analogRead(ANALOG_DOT) < 600 ) keyerControl |= DIT_L;
//if (analogRead(ANALOG_DASH) < 600 ) keyerControl |= DAH_L;
}
*/
//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) {
int paddle = analogRead(ANALOG_KEYER);
unsigned char tmpKeyerControl;
int paddle = analogRead(ANALOG_KEYER);
if (paddle > 800) // above 4v is up
tmpKeyerControl = 0;
else if (paddle > 600) // 4-3v is DASH
if (paddle >= cwAdcDashFrom && paddle <= cwAdcDashTo)
tmpKeyerControl |= DAH_L;
else if (paddle > 300) //1-2v is DOT
else if (paddle >= cwAdcDotFrom && paddle <= cwAdcDotTo)
tmpKeyerControl |= DIT_L;
else if (paddle > 50)
tmpKeyerControl |= (DAH_L | DIT_L) ; //both are between 1 and 2v
else
tmpKeyerControl = 0 ; //STRAIGHT KEY in original code
//keyerControl |= (DAH_L | DIT_L) ; //STRAIGHT KEY in original code
if (isUpdateKeyState == 1) {
keyerControl |= tmpKeyerControl;
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;
//if (analogRead(ANALOG_DOT) < 600 ) keyerControl |= DIT_L;
//if (analogRead(ANALOG_DASH) < 600 ) keyerControl |= DAH_L;
}
/*****************************************************************************
// New logic, by RON
// modified by KD8CEC
******************************************************************************/
void cwKeyer(void){
byte paddle;
lastPaddle = 0;
int dot,dash;
bool continue_loop = true;
unsigned tmpKeyControl = 0;
if( Iambic_Key ){
while(continue_loop){
switch (keyerState) {
case IDLE:
tmpKeyControl = update_PaddleLatch(0);
if ( tmpKeyControl == DAH_L || tmpKeyControl == DIT_L ||
tmpKeyControl == (DAH_L | DIT_L) || (keyerControl & 0x03)) {
//DIT or DASH or current state DIT & DASH
//(analogRead(ANALOG_DOT) < 600) || //DIT
//(analogRead(ANALOG_DASH) < 600) || //DIT
// (keyerControl & 0x03)) {
update_PaddleLatch(1);
keyerState = CHK_DIT;
}else{
if( Iambic_Key ) {
while(continue_loop) {
switch (keyerState) {
case IDLE:
tmpKeyControl = update_PaddleLatch(0);
if ( tmpKeyControl == DAH_L || tmpKeyControl == DIT_L ||
tmpKeyControl == (DAH_L | DIT_L) || (keyerControl & 0x03)) {
update_PaddleLatch(1);
keyerState = CHK_DIT;
}else{
if (0 < cwTimeout && cwTimeout < millis()){
cwTimeout = 0;
stopTx();
}
continue_loop = false;
}
break;
case CHK_DIT:
if (keyerControl & DIT_L) {
keyerControl |= DIT_PROC;
ktimer = cwSpeed;
keyerState = KEYED_PREP;
}else{
keyerState = CHK_DAH;
}
break;
case CHK_DAH:
if (keyerControl & DAH_L) {
ktimer = cwSpeed*3;
keyerState = KEYED_PREP;
}else{
keyerState = IDLE;
}
break;
case KEYED_PREP:
ktimer += millis(); // set ktimer to interval end time
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
keyerState = KEYED; // next state
if (!inTx){
keyDown = 0;
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
startTx(TX_CW, 1);
}
cwKeydown();
break;
case KEYED:
if (millis() > ktimer) { // are we at end of key down ?
cwKeyUp();
ktimer = millis() + cwSpeed; // inter-element time
keyerState = INTER_ELEMENT; // next state
}else if (keyerControl & IAMBICB) {
update_PaddleLatch(1); // early paddle latch in Iambic B mode
}
break;
case INTER_ELEMENT:
// Insert time between dits/dahs
update_PaddleLatch(1); // latch paddle state
if (millis() > ktimer) { // are we at end of inter-space ?
if (keyerControl & DIT_PROC) { // was it a dit or dah ?
keyerControl &= ~(DIT_L + DIT_PROC); // clear two bits
keyerState = CHK_DAH; // dit done, check for dah
}else{
keyerControl &= ~(DAH_L); // clear dah latch
keyerState = IDLE; // go idle
}
}
break;
}
Check_Cat(3);
} //end of while
}
else{
while(1){
if (update_PaddleLatch(0) == DIT_L) {
// if we are here, it is only because the key is pressed
if (!inTx){
keyDown = 0;
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
startTx(TX_CW, 1);
}
cwKeydown();
while ( update_PaddleLatch(0) == DIT_L )
delay_background(1, 3);
cwKeyUp();
}
else{
if (0 < cwTimeout && cwTimeout < millis()){
cwTimeout = 0;
keyDown = 0;
stopTx();
}
continue_loop = false;
if (!cwTimeout)
return;
// got back to the beginning of the loop, if no further activity happens on straight key
// we will time out, and return out of this routine
//delay(5);
delay_background(5, 3);
continue;
}
break;
case CHK_DIT:
if (keyerControl & DIT_L) {
keyerControl |= DIT_PROC;
ktimer = cwSpeed;
keyerState = KEYED_PREP;
}else{
keyerState = CHK_DAH;
}
break;
case CHK_DAH:
if (keyerControl & DAH_L) {
ktimer = cwSpeed*3;
keyerState = KEYED_PREP;
}else{
keyerState = IDLE;
}
break;
case KEYED_PREP:
ktimer += millis(); // set ktimer to interval end time
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
keyerState = KEYED; // next state
if (!inTx){
keyDown = 0;
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
startTx(TX_CW, 0);
}
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;
}
} //end of while
}else{
while(1){
//if (analogRead(ANALOG_DOT) < 600){
if (update_PaddleLatch(0) == DIT_L) {
// if we are here, it is only because the key is pressed
if (!inTx){
keyDown = 0;
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
startTx(TX_CW, 0);
}
// start the transmission)
cwKeydown();
//while ( analogRead(ANALOG_DOT) < 600 ) delay(1);
while ( update_PaddleLatch(0) == DIT_L ) delay(1);
cwKeyUp();
}else{
if (0 < cwTimeout && cwTimeout < millis()){
cwTimeout = 0;
keyDown = 0;
stopTx();
}
if (!cwTimeout)
return;
// got back to the beginning of the loop, if no further activity happens on straight key
// we will time out, and return out of this routine
delay(5);
continue;
}
} //end of else
Check_Cat(2);
} //end of while
} //end of elese
}
}
//=======================================================================================

View File

@@ -13,6 +13,7 @@
#define printLineF1(x) (printLineF(1, x))
#define printLineF2(x) (printLineF(0, x))
//Ham band move by KD8CEC
void menuBand(int btn){
int knob = 0;
int stepChangeCount = 0;
@@ -117,6 +118,7 @@ void menuBand(int btn){
menuOn = 0;
}
//Convert Mode, Number by KD8CEC
//0: default, 1:not use, 2:LSB, 3:USB, 4:CW, 5:AM, 6:FM
byte modeToByte(){
if (isUSB)
@@ -125,12 +127,15 @@ byte modeToByte(){
return 2;
}
//Convert Number to Mode by KD8CEC
void byteToMode(byte modeValue){
if (modeValue == 3)
isUSB = 1;
else
isUSB = 0;
}
//Convert Number to Mode by KD8CEC
void byteWithFreqToMode(byte modeValue){
if (modeValue == 3)
isUSB = 1;
@@ -140,6 +145,7 @@ void byteWithFreqToMode(byte modeValue){
isUSB = 0;
}
//VFO Toggle and save VFO Information, modified by KD8CEC
void menuVfoToggle(int btn, char isUseDelayTime)
{
if (!btn){
@@ -229,6 +235,189 @@ void menuSidebandToggle(int btn){
}
}
/*
//Select CW Key Type by KD8CEC
void menuSetupKeyType(int btn){
if (!btn && digitalRead(PTT) == HIGH){
if (Iambic_Key)
printLineF2(F("Key: Straight?"));
else
printLineF2(F("Key: Fn=A, PTT=B"));
}
else {
if (Iambic_Key)
{
printLineF2(F("Straight Key!"));
Iambic_Key = false;
}
else
{
Iambic_Key = true;
if (btn)
{
keyerControl &= ~IAMBICB;
printLineF2(F("IAMBICA Key!"));
}
else
{
keyerControl |= IAMBICB;
printLineF2(F("IAMBICB Key!"));
}
}
delay_background(500, 0);
printLine2ClearAndUpdate();
menuOn = 0;
}
}
*/
//Select CW Key Type by KD8CEC
void menuSetupKeyType(int btn){
int knob = 0;
int selectedKeyType = 0;
int moveStep = 0;
if (!btn && digitalRead(PTT) == HIGH){
printLineF2(F("Change Key Type?"));
}
else {
printLineF2(F("Press PTT to set"));
delay_background(500, 0);
selectedKeyType = cwKeyType;
while(!btnDown() && digitalRead(PTT) == HIGH){
//Display Key Type
if (selectedKeyType == 0)
printLineF1(F("Straight"));
else if (selectedKeyType == 1)
printLineF1(F("IAMBICA"));
else if (selectedKeyType == 2)
printLineF1(F("IAMBICB"));
knob = enc_read();
if (knob != 0)
{
moveStep += (knob > 0 ? 1 : -1);
if (selectedKeyType > 0 && moveStep < -3) {
selectedKeyType--;
moveStep = 0;
}
else if (selectedKeyType < 2 && moveStep > 3) {
selectedKeyType++;
moveStep = 0;
}
}
Check_Cat(0); //To prevent disconnections
}
//save the setting
if (digitalRead(PTT) == LOW){
printLineF2(F("CW Key Type set!"));
cwKeyType = selectedKeyType;
EEPROM.put(CW_KEY_TYPE, cwKeyType);
if (cwKeyType == 0)
Iambic_Key = false;
else
{
Iambic_Key = true;
if (cwKeyType = 1)
keyerControl &= ~IAMBICB;
else
keyerControl |= IAMBICB;
}
delay_background(2000, 0);
}
printLine2ClearAndUpdate();
menuOn = 0;
}
}
//Analog pin monitoring with CW Key and function keys connected.
//by KD8CEC
void menuADCMonitor(int btn){
int adcPinA0 = 0; //A0(BLACK, EncoderA)
int adcPinA1 = 0; //A1(BROWN, EncoderB)
int adcPinA2 = 0; //A2(RED, Function Key)
int adcPinA3 = 0; //A3(ORANGE, CW Key)
int adcPinA6 = 0; //A6(BLUE, Ptt)
int adcPinA7 = 0; //A7(VIOLET, Spare)
unsigned long pressKeyTime = 0;
if (!btn){
printLineF2(F("ADC Line Monitor"));
return;
}
printLineF2(F("Exit:Long PTT"));
delay_background(2000, 0);
printLineF1(F("A0 A1 A2"));
printLineF2(F("A3 A6 A7"));
delay_background(3000, 0);
while (true) {
adcPinA0 = analogRead(A0); //A0(BLACK, EncoderA)
adcPinA1 = analogRead(A1); //A1(BROWN, EncoderB)
adcPinA2 = analogRead(A2); //A2(RED, Function Key)
adcPinA3 = analogRead(A3); //A3(ORANGE, CW Key)
adcPinA6 = analogRead(A6); //A6(BLUE, Ptt)
adcPinA7 = analogRead(A7); //A7(VIOLET, Spare)
/*
sprintf(c, "%4d %4d %4d", adcPinA0, adcPinA1, adcPinA2);
printLine1(c);
sprintf(c, "%4d %4d %4d", adcPinA3, adcPinA6, adcPinA7);
printLine2(c);
*/
if (adcPinA6 < 10) {
if (pressKeyTime == 0)
pressKeyTime = millis();
else if (pressKeyTime < (millis() - 3000))
break;
}
else
pressKeyTime = 0;
ltoa(adcPinA0, c, 10);
//strcat(b, c);
strcpy(b, c);
strcat(b, ", ");
ltoa(adcPinA1, c, 10);
strcat(b, c);
strcat(b, ", ");
ltoa(adcPinA2, c, 10);
strcat(b, c);
printLine1(b);
//strcpy(b, " ");
ltoa(adcPinA3, c, 10);
strcpy(b, c);
strcat(b, ", ");
ltoa(adcPinA6, c, 10);
strcat(b, c);
strcat(b, ", ");
ltoa(adcPinA7, c, 10);
strcat(b, c);
printLine2(b);
delay_background(200, 0);
} //end of while
printLine2ClearAndUpdate();
menuOn = 0;
}
//Function to disbled transmission
//by KD8CEC
void menuTxOnOff(int btn, byte optionType){
if (!btn){
if ((isTxType & optionType) == 0)
@@ -342,6 +531,7 @@ void menuCWSpeed(int btn){
menuOn = 0;
}
//Builtin CW Keyer Logic by KD8CEC
void menuCWAutoKey(int btn){
if (!btn){
printLineF2(F("CW AutoKey Mode?"));
@@ -365,6 +555,7 @@ void menuCWAutoKey(int btn){
menuOn = 0;
}
//Modified by KD8CEC
void menuSetupCwDelay(int btn){
int knob = 0;
int tmpCWDelay = cwDelayTime * 10;
@@ -413,6 +604,7 @@ void menuSetupCwDelay(int btn){
menuOn = 0;
}
//CW Time delay by KD8CEC
void menuSetupTXCWInterval(int btn){
int knob = 0;
int tmpTXCWInterval = delayBeforeCWStartTime * 2;
@@ -608,7 +800,6 @@ void menuSetupCalibration(int btn){
menuOn = 0;
}
void printCarrierFreq(unsigned long freq){
memset(c, 0, sizeof(c));
@@ -624,6 +815,7 @@ void printCarrierFreq(unsigned long freq){
printLine2(c);
}
//modified by KD8CEC (just 1 line remarked //usbCarrier = ...
void menuSetupCarrier(int btn){
int knob = 0;
unsigned long prevCarrier;
@@ -677,6 +869,7 @@ void menuSetupCarrier(int btn){
menuOn = 0;
}
//Modified by KD8CEC
void menuSetupCwTone(int btn){
int knob = 0;
int prev_sideTone;
@@ -725,6 +918,7 @@ void menuSetupCwTone(int btn){
menuOn = 0;
}
//Lock Dial move by KD8CEC
void setDialLock(byte tmpLock, byte fromMode) {
if (tmpLock == 1)
isDialLock |= (vfoActive == VFO_A ? 0x01 : 0x02);
@@ -747,6 +941,7 @@ unsigned int btnDownTimeCount;
#define PRESS_ADJUST_TUNE 1000
#define PRESS_LOCK_CONTROL 2000
//Modified by KD8CEC
void doMenu(){
int select=0, i,btnState;
char isNeedDisplay = 0;
@@ -830,7 +1025,7 @@ void doMenu(){
btnState = btnDown();
if (i > 0){
if (modeCalibrate && select + i < 150)
if (modeCalibrate && select + i < 170)
select += i;
if (!modeCalibrate && select + i < 80)
select += i;
@@ -868,8 +1063,12 @@ void doMenu(){
else if (select < 130 && modeCalibrate)
menuSetupTXCWInterval(btnState);
else if (select < 140 && modeCalibrate)
menuTxOnOff(btnState, 0x01); //TX OFF / ON
menuSetupKeyType(btnState);
else if (select < 150 && modeCalibrate)
menuADCMonitor(btnState);
else if (select < 160 && modeCalibrate)
menuTxOnOff(btnState, 0x01); //TX OFF / ON
else if (select < 170 && modeCalibrate)
menuExit(btnState);
Check_Cat(0); //To prevent disconnections

View File

@@ -116,6 +116,9 @@ void drawMeter(int8_t needle){
// 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);
@@ -145,6 +148,9 @@ void printLineF(char linenmbr, const __FlashStringHelper *c)
#define LCD_MAX_COLUMN 16
void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex) {
if ((displayOption1 & 0x01) == 0x01)
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
lcd.setCursor(lcdColumn, linenmbr);
for (byte i = eepromStartIndex; i <= eepromEndIndex; i++)
@@ -168,6 +174,12 @@ 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,"");
@@ -179,6 +191,7 @@ void printLine2Clear(){
void printLine2ClearAndUpdate(){
printLine(0, "");
line2DisplayStatus = 0;
updateDisplay();
}
@@ -251,18 +264,22 @@ void updateDisplay() {
// 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,1);
lcd.setCursor(5,diplayVFOLine);
lcd.write((uint8_t)0);
}
else if (isCWAutoMode == 2){
lcd.setCursor(5,1);
lcd.setCursor(5,diplayVFOLine);
lcd.write(0x7E);
}
else
{
lcd.setCursor(5,1);
lcd.setCursor(5,diplayVFOLine);
lcd.write(":");
}