Compare commits
16 Commits
meter-to-t
...
integratio
Author | SHA1 | Date | |
---|---|---|---|
|
47840e09dd | ||
|
d2213e34ff | ||
|
814fe6c733 | ||
|
c3cc9a7cf7 | ||
|
aeeec69daf | ||
|
702f370d1b | ||
|
b9be616361 | ||
|
4186fdcdd4 | ||
|
e62e3ef548 | ||
|
deb0aca5fe | ||
|
04d5f3ba12 | ||
|
ba744f5b7a | ||
|
4e818b6a89 | ||
|
b2cb1a26ba | ||
|
6b365beac0 | ||
|
88143f57a2 |
@@ -1,4 +1,4 @@
|
|||||||
//Firmware Version
|
//Firmware Version
|
||||||
//+ : This symbol identifies the firmware.
|
//+ : This symbol identifies the firmware.
|
||||||
// It was originally called 'CEC V1.072' but it is too long to waste the LCD window.
|
// It was originally called 'CEC V1.072' but it is too long to waste the LCD window.
|
||||||
// I do not want to make this Firmware users's uBITX messy with my callsign.
|
// I do not want to make this Firmware users's uBITX messy with my callsign.
|
||||||
@@ -122,7 +122,8 @@ char vfoActive = VFO_A;
|
|||||||
int8_t meter_reading = 0; // a -1 on meter makes it invisible
|
int8_t meter_reading = 0; // a -1 on meter makes it invisible
|
||||||
unsigned long vfoA=7150000L, vfoB=14200000L, sideTone=800, usbCarrier, cwmCarrier;
|
unsigned long vfoA=7150000L, vfoB=14200000L, sideTone=800, usbCarrier, cwmCarrier;
|
||||||
unsigned long vfoA_eeprom, vfoB_eeprom; //for protect eeprom life
|
unsigned long vfoA_eeprom, vfoB_eeprom; //for protect eeprom life
|
||||||
unsigned long frequency, ritRxFrequency, ritTxFrequency; //frequency is the current frequency on the dial
|
unsigned long frequency;
|
||||||
|
unsigned long ritRxFrequency, ritTxFrequency; //frequency is the current frequency on the dial
|
||||||
|
|
||||||
unsigned int cwSpeed = 100; //this is actuall the dot period in milliseconds
|
unsigned int cwSpeed = 100; //this is actuall the dot period in milliseconds
|
||||||
extern int32_t calibration;
|
extern int32_t calibration;
|
||||||
@@ -316,6 +317,17 @@ unsigned long delayBeforeTime = 0;
|
|||||||
byte delay_background(unsigned delayTime, byte fromType){ //fromType : 4 autoCWKey -> Check Paddle
|
byte delay_background(unsigned delayTime, byte fromType){ //fromType : 4 autoCWKey -> Check Paddle
|
||||||
delayBeforeTime = millis();
|
delayBeforeTime = millis();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* KC4UPR - IOP review, 2020-05-03
|
||||||
|
*
|
||||||
|
* I don't see anything in here that is either important to, or will adversely affect, IOP
|
||||||
|
* operation. I'm not planning on using the uBITX autokeyer (since all keying will be in the
|
||||||
|
* IOP), so neither getPaddle() nor autoSendPTTCheck() will be issues. I do need to look into
|
||||||
|
* overall CAT operation, in general.
|
||||||
|
*
|
||||||
|
* UPDATE: Fixed getPaddle() to be compatible.
|
||||||
|
*/
|
||||||
|
|
||||||
while (millis() - delayBeforeTime <= delayTime) {
|
while (millis() - delayBeforeTime <= delayTime) {
|
||||||
|
|
||||||
if (fromType == 4)
|
if (fromType == 4)
|
||||||
@@ -327,12 +339,12 @@ byte delay_background(unsigned delayTime, byte fromType){ //fromType : 4 autoCWK
|
|||||||
//Check PTT while auto Sending
|
//Check PTT while auto Sending
|
||||||
autoSendPTTCheck();
|
autoSendPTTCheck();
|
||||||
|
|
||||||
Check_Cat(3);
|
//Check_Cat(3);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Background Work
|
//Background Work
|
||||||
Check_Cat(fromType);
|
//Check_Cat(fromType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,6 +690,10 @@ void ritDisable(){
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void checkPTT(){
|
void checkPTT(){
|
||||||
|
/*
|
||||||
|
* KC4UPR - note that some of this is superfluous now that checkPTT() is only executed
|
||||||
|
* in SSB mode, and cwKeyer is only executed in CW mode...
|
||||||
|
*/
|
||||||
//we don't check for ptt when transmitting cw
|
//we don't check for ptt when transmitting cw
|
||||||
if (cwTimeout > 0)
|
if (cwTimeout > 0)
|
||||||
return;
|
return;
|
||||||
@@ -790,7 +806,7 @@ void checkButton(){
|
|||||||
//wait for the button to go up again
|
//wait for the button to go up again
|
||||||
while(keyStatus == getBtnStatus()) {
|
while(keyStatus == getBtnStatus()) {
|
||||||
delay(10);
|
delay(10);
|
||||||
Check_Cat(0);
|
//Check_Cat(0);
|
||||||
}
|
}
|
||||||
//delay(50);//debounce
|
//delay(50);//debounce
|
||||||
}
|
}
|
||||||
@@ -809,7 +825,7 @@ void checkButton(){
|
|||||||
//wait for the button to go up again
|
//wait for the button to go up again
|
||||||
while(btnDown()) {
|
while(btnDown()) {
|
||||||
delay(10);
|
delay(10);
|
||||||
Check_Cat(0);
|
//Check_Cat(0);
|
||||||
}
|
}
|
||||||
//delay(50);//debounce
|
//delay(50);//debounce
|
||||||
}
|
}
|
||||||
@@ -1386,7 +1402,8 @@ void setup()
|
|||||||
//printLineF(1, FIRMWARE_VERSION_INFO);
|
//printLineF(1, FIRMWARE_VERSION_INFO);
|
||||||
DisplayVersionInfo(FIRMWARE_VERSION_INFO);
|
DisplayVersionInfo(FIRMWARE_VERSION_INFO);
|
||||||
|
|
||||||
Init_Cat(38400, SERIAL_8N1);
|
//Init_Cat(38400, SERIAL_8N1);
|
||||||
|
Serial.begin(38400);
|
||||||
initSettings();
|
initSettings();
|
||||||
initPorts();
|
initPorts();
|
||||||
|
|
||||||
@@ -1456,18 +1473,48 @@ void checkAutoSaveFreqMode()
|
|||||||
saveCheckTime = 0; //for reduce cpu use rate
|
saveCheckTime = 0; //for reduce cpu use rate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rigState.vfo[0] = vfoA;
|
||||||
|
rigState.vfo[1] = vfoB;
|
||||||
|
rigState.rit = ritRxFrequency - frequency;
|
||||||
|
rigState.flags = 0;
|
||||||
|
rigState.flags |= (vfoActive == VFO_B ? UBITX_VFOB_FLAG : 0);
|
||||||
|
rigState.flags |= (cwMode != 0 ? UBITX_CW_FLAG : 0);
|
||||||
|
rigState.flags |= (isUSB != 0 ? UBITX_USB_FLAG : 0);
|
||||||
|
rigState.flags |= (splitOn != 0 ? UBITX_SPLIT_FLAG : 0);
|
||||||
|
rigState.flags |= (ritOn != 0 ? UBITX_RIT_FLAG : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop(){
|
void loop(){
|
||||||
if (isCWAutoMode == 0){ //when CW AutoKey Mode, disable this process
|
/*
|
||||||
if (!txCAT)
|
* KC4UPR - IOP update, 2020-05-03
|
||||||
|
*
|
||||||
|
* Getting rid of the autokeyer code... not planning on using, since any autokeying
|
||||||
|
* would actually be done by the IOP. We'll check the PTT, but only in SSB mode
|
||||||
|
* (same line as CW, so it would be caught by cwKeyer() in CW mode).
|
||||||
|
*
|
||||||
|
* Only check the CW keyer if we are in one of the CW modes. Why? Because we
|
||||||
|
* are using the same input for PTT and CW.
|
||||||
|
*/
|
||||||
|
// if (isCWAutoMode == 0){ //when CW AutoKey Mode, disable this process
|
||||||
|
// if (!txCAT)
|
||||||
|
// checkPTT();
|
||||||
|
// checkButton();
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// controlAutoCW();
|
||||||
|
// KC4UPR: Note, implementation below leaves no manual way to abort TX due to CAT. May
|
||||||
|
// want to add in a way to interrupt CAT transmission with a PTT/CW event.
|
||||||
|
//if (!txCAT) {
|
||||||
|
if (cwMode == 0) {
|
||||||
checkPTT();
|
checkPTT();
|
||||||
checkButton();
|
} else {
|
||||||
}
|
cwKeyer();
|
||||||
else
|
}
|
||||||
controlAutoCW();
|
checkButton();
|
||||||
|
//}
|
||||||
cwKeyer();
|
|
||||||
|
//cwKeyer();
|
||||||
|
|
||||||
//tune only when not tranmsitting
|
//tune only when not tranmsitting
|
||||||
if (!inTx){
|
if (!inTx){
|
||||||
@@ -1487,7 +1534,7 @@ void loop(){
|
|||||||
} //end of check TX Status
|
} //end of check TX Status
|
||||||
|
|
||||||
//we check CAT after the encoder as it might put the radio into TX
|
//we check CAT after the encoder as it might put the radio into TX
|
||||||
Check_Cat(inTx? 1 : 0);
|
//Check_Cat(inTx? 1 : 0);
|
||||||
|
|
||||||
//for SEND SW Serial
|
//for SEND SW Serial
|
||||||
#ifdef USE_SW_SERIAL
|
#ifdef USE_SW_SERIAL
|
||||||
|
1
Raduino/RigState.h
Symbolic link
1
Raduino/RigState.h
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../TeensyDSP/RigState.h
|
@@ -19,11 +19,13 @@
|
|||||||
|
|
||||||
#include <Arduino.h> //for Linux, On Linux it is case sensitive.
|
#include <Arduino.h> //for Linux, On Linux it is case sensitive.
|
||||||
|
|
||||||
|
#include "RigState.h"
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// Compile Option
|
// Compile Option
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
//Ubitx Board Version
|
//Ubitx Board Version
|
||||||
#define UBITX_BOARD_VERSION 2 //v1 ~ v4 : 4, v5: 5
|
#define UBITX_BOARD_VERSION 5 //v1 ~ v4 : 4, v5: 5
|
||||||
|
|
||||||
//Depending on the type of LCD mounted on the uBITX, uncomment one of the options below.
|
//Depending on the type of LCD mounted on the uBITX, uncomment one of the options below.
|
||||||
//You must select only one.
|
//You must select only one.
|
||||||
@@ -48,8 +50,8 @@
|
|||||||
//#define USE_CUSTOM_LPF_FILTER //LPF FILTER MOD
|
//#define USE_CUSTOM_LPF_FILTER //LPF FILTER MOD
|
||||||
|
|
||||||
//#define ENABLE_FACTORYALIGN
|
//#define ENABLE_FACTORYALIGN
|
||||||
#define FACTORY_RECOVERY_BOOTUP //Whether to enter Factory Recovery mode by pressing FKey and turning on power
|
//#define FACTORY_RECOVERY_BOOTUP //Whether to enter Factory Recovery mode by pressing FKey and turning on power
|
||||||
#define ENABLE_ADCMONITOR //Starting with Version 1.07, you can read ADC values directly from uBITX Manager. So this function is not necessary.
|
//#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_MASTER_ADDRESS; //0x27 //if Set I2C Address by uBITX Manager, read from EEProm
|
||||||
extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode
|
extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode
|
||||||
@@ -253,6 +255,12 @@ extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode
|
|||||||
#define I2CMETER_CALCR 0x55 //Calculated SWR Meter
|
#define I2CMETER_CALCR 0x55 //Calculated SWR Meter
|
||||||
#define I2CMETER_UNCALCR 0x54 //Uncalculated SWR Meter
|
#define I2CMETER_UNCALCR 0x54 //Uncalculated SWR Meter
|
||||||
|
|
||||||
|
// Raduino provides updated data to TeensyDSP
|
||||||
|
#define I2CMETER_RIGINF 0x50
|
||||||
|
|
||||||
|
// Raduino requests any CAT updates from TeensyDSP
|
||||||
|
#define I2CMETER_REQCAT 0x51
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// for public, Variable, functions
|
// for public, Variable, functions
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
@@ -332,4 +340,10 @@ extern void DisplayVersionInfo(const char* fwVersionInfo);
|
|||||||
//I2C Signal Meter, Version 1.097
|
//I2C Signal Meter, Version 1.097
|
||||||
extern int GetI2CSmeterValue(int valueType); //ubitx_ui.ino
|
extern int GetI2CSmeterValue(int valueType); //ubitx_ui.ino
|
||||||
|
|
||||||
|
extern void doRaduinoToTeensy(UBitxRigState* r);
|
||||||
|
extern void updateStateFromRaduino(UBitxRigState& r);
|
||||||
|
extern void updateRaduinoFromState(UBitxRigState& r);
|
||||||
|
|
||||||
|
extern UBitxRigState rigState;
|
||||||
|
|
||||||
#endif //end of if header define
|
#endif //end of if header define
|
||||||
|
@@ -39,6 +39,22 @@ char lastPaddle = 0;
|
|||||||
|
|
||||||
//reads the analog keyer pin and reports the paddle
|
//reads the analog keyer pin and reports the paddle
|
||||||
byte getPaddle(){
|
byte getPaddle(){
|
||||||
|
/*
|
||||||
|
* KC4UPR - IOP update, 2020-05-03
|
||||||
|
*
|
||||||
|
* Modifying this for the uBITX IOP. Big picture:
|
||||||
|
*
|
||||||
|
* (1) It uses the PTT input line.
|
||||||
|
*
|
||||||
|
* (2) It's always "straight key" mode (the IOP provides the keyer).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (digitalRead(PTT) == 1) // key/PTT is up
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return PADDLE_STRAIGHT;
|
||||||
|
|
||||||
|
/*
|
||||||
int paddle = analogRead(ANALOG_KEYER);
|
int paddle = analogRead(ANALOG_KEYER);
|
||||||
|
|
||||||
if (paddle > 800) // above 4v is up
|
if (paddle > 800) // above 4v is up
|
||||||
@@ -52,6 +68,7 @@ byte getPaddle(){
|
|||||||
return PADDLE_BOTH; //both are between 1 and 2v
|
return PADDLE_BOTH; //both are between 1 and 2v
|
||||||
else
|
else
|
||||||
return PADDLE_STRAIGHT; //less than 1v is the straight key
|
return PADDLE_STRAIGHT; //less than 1v is the straight key
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,9 +113,20 @@ unsigned char keyerState = IDLE;
|
|||||||
//Below is a test to reduce the keying error. do not delete lines
|
//Below is a test to reduce the keying error. do not delete lines
|
||||||
//create by KD8CEC for compatible with new CW Logic
|
//create by KD8CEC for compatible with new CW Logic
|
||||||
char update_PaddleLatch(byte isUpdateKeyState) {
|
char update_PaddleLatch(byte isUpdateKeyState) {
|
||||||
|
/*
|
||||||
|
* KC4UPR - IOP update, 2020-05-03
|
||||||
|
*
|
||||||
|
* Modifying this for the uBITX IOP. Big picture:
|
||||||
|
*
|
||||||
|
* No iambic keyer. It's always "straight key" based on the IOP.
|
||||||
|
*
|
||||||
|
* It uses the PTT line.
|
||||||
|
*/
|
||||||
|
return (digitalRead(PTT) ? 0 : DIT_L);
|
||||||
|
/*
|
||||||
unsigned char tmpKeyerControl = 0;
|
unsigned char tmpKeyerControl = 0;
|
||||||
int paddle = analogRead(ANALOG_KEYER);
|
int paddle = analogRead(ANALOG_KEYER);
|
||||||
|
|
||||||
if (paddle >= cwAdcDashFrom && paddle <= cwAdcDashTo)
|
if (paddle >= cwAdcDashFrom && paddle <= cwAdcDashTo)
|
||||||
tmpKeyerControl |= DAH_L;
|
tmpKeyerControl |= DAH_L;
|
||||||
else if (paddle >= cwAdcDotFrom && paddle <= cwAdcDotTo)
|
else if (paddle >= cwAdcDotFrom && paddle <= cwAdcDotTo)
|
||||||
@@ -119,6 +147,7 @@ char update_PaddleLatch(byte isUpdateKeyState) {
|
|||||||
keyerControl |= tmpKeyerControl;
|
keyerControl |= tmpKeyerControl;
|
||||||
|
|
||||||
return tmpKeyerControl;
|
return tmpKeyerControl;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@@ -126,106 +155,113 @@ char update_PaddleLatch(byte isUpdateKeyState) {
|
|||||||
// modified by KD8CEC
|
// modified by KD8CEC
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void cwKeyer(void){
|
void cwKeyer(void){
|
||||||
lastPaddle = 0;
|
/*
|
||||||
bool continue_loop = true;
|
* KC4UPR - IOP update, 2020-05-03
|
||||||
unsigned tmpKeyControl = 0;
|
*
|
||||||
|
* Modifying this for the uBITX IOP. Big picture:
|
||||||
if( Iambic_Key ) {
|
*
|
||||||
while(continue_loop) {
|
* No iambic keyer. It's always "straight key" based on the IOP.
|
||||||
switch (keyerState) {
|
*/
|
||||||
case IDLE:
|
// lastPaddle = 0;
|
||||||
tmpKeyControl = update_PaddleLatch(0);
|
// bool continue_loop = true;
|
||||||
if ( tmpKeyControl == DAH_L || tmpKeyControl == DIT_L ||
|
// unsigned tmpKeyControl = 0;
|
||||||
tmpKeyControl == (DAH_L | DIT_L) || (keyerControl & 0x03)) {
|
//
|
||||||
update_PaddleLatch(1);
|
// if( Iambic_Key ) {
|
||||||
keyerState = CHK_DIT;
|
// while(continue_loop) {
|
||||||
}else{
|
// switch (keyerState) {
|
||||||
if (0 < cwTimeout && cwTimeout < millis()){
|
// case IDLE:
|
||||||
cwTimeout = 0;
|
// tmpKeyControl = update_PaddleLatch(0);
|
||||||
stopTx();
|
// if ( tmpKeyControl == DAH_L || tmpKeyControl == DIT_L ||
|
||||||
}
|
// tmpKeyControl == (DAH_L | DIT_L) || (keyerControl & 0x03)) {
|
||||||
continue_loop = false;
|
// update_PaddleLatch(1);
|
||||||
}
|
// keyerState = CHK_DIT;
|
||||||
break;
|
// }else{
|
||||||
|
// if (0 < cwTimeout && cwTimeout < millis()){
|
||||||
case CHK_DIT:
|
// cwTimeout = 0;
|
||||||
if (keyerControl & DIT_L) {
|
// stopTx();
|
||||||
keyerControl |= DIT_PROC;
|
// }
|
||||||
ktimer = cwSpeed;
|
// continue_loop = false;
|
||||||
keyerState = KEYED_PREP;
|
// }
|
||||||
}else{
|
// break;
|
||||||
keyerState = CHK_DAH;
|
//
|
||||||
}
|
// case CHK_DIT:
|
||||||
break;
|
// if (keyerControl & DIT_L) {
|
||||||
|
// keyerControl |= DIT_PROC;
|
||||||
case CHK_DAH:
|
// ktimer = cwSpeed;
|
||||||
if (keyerControl & DAH_L) {
|
// keyerState = KEYED_PREP;
|
||||||
ktimer = cwSpeed*3;
|
// }else{
|
||||||
keyerState = KEYED_PREP;
|
// keyerState = CHK_DAH;
|
||||||
}else{
|
// }
|
||||||
keyerState = IDLE;
|
// break;
|
||||||
}
|
//
|
||||||
break;
|
// case CHK_DAH:
|
||||||
|
// if (keyerControl & DAH_L) {
|
||||||
case KEYED_PREP:
|
// ktimer = cwSpeed*3;
|
||||||
//modified KD8CEC
|
// keyerState = KEYED_PREP;
|
||||||
/*
|
// }else{
|
||||||
ktimer += millis(); // set ktimer to interval end time
|
// keyerState = IDLE;
|
||||||
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
// }
|
||||||
keyerState = KEYED; // next state
|
// break;
|
||||||
if (!inTx){
|
//
|
||||||
//DelayTime Option
|
// case KEYED_PREP:
|
||||||
delay_background(delayBeforeCWStartTime * 2, 2);
|
// //modified KD8CEC
|
||||||
|
// /*
|
||||||
keyDown = 0;
|
// ktimer += millis(); // set ktimer to interval end time
|
||||||
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
// keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
||||||
startTx(TX_CW, 1);
|
// keyerState = KEYED; // next state
|
||||||
}
|
// if (!inTx){
|
||||||
*/
|
// //DelayTime Option
|
||||||
if (!inTx){
|
// delay_background(delayBeforeCWStartTime * 2, 2);
|
||||||
//DelayTime Option
|
//
|
||||||
delay_background(delayBeforeCWStartTime * 2, 2);
|
// keyDown = 0;
|
||||||
|
// cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
||||||
keyDown = 0;
|
// startTx(TX_CW, 1);
|
||||||
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
// }
|
||||||
startTx(TX_CW, 1);
|
// */
|
||||||
}
|
// if (!inTx){
|
||||||
ktimer += millis(); // set ktimer to interval end time
|
// //DelayTime Option
|
||||||
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
// delay_background(delayBeforeCWStartTime * 2, 2);
|
||||||
keyerState = KEYED; // next state
|
//
|
||||||
|
// keyDown = 0;
|
||||||
cwKeydown();
|
// cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
||||||
break;
|
// startTx(TX_CW, 1);
|
||||||
|
// }
|
||||||
case KEYED:
|
// ktimer += millis(); // set ktimer to interval end time
|
||||||
if (millis() > ktimer) { // are we at end of key down ?
|
// keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
||||||
cwKeyUp();
|
// keyerState = KEYED; // next state
|
||||||
ktimer = millis() + cwSpeed; // inter-element time
|
//
|
||||||
keyerState = INTER_ELEMENT; // next state
|
// cwKeydown();
|
||||||
}else if (keyerControl & IAMBICB) {
|
// break;
|
||||||
update_PaddleLatch(1); // early paddle latch in Iambic B mode
|
//
|
||||||
}
|
// case KEYED:
|
||||||
break;
|
// if (millis() > ktimer) { // are we at end of key down ?
|
||||||
|
// cwKeyUp();
|
||||||
case INTER_ELEMENT:
|
// ktimer = millis() + cwSpeed; // inter-element time
|
||||||
// Insert time between dits/dahs
|
// keyerState = INTER_ELEMENT; // next state
|
||||||
update_PaddleLatch(1); // latch paddle state
|
// }else if (keyerControl & IAMBICB) {
|
||||||
if (millis() > ktimer) { // are we at end of inter-space ?
|
// update_PaddleLatch(1); // early paddle latch in Iambic B mode
|
||||||
if (keyerControl & DIT_PROC) { // was it a dit or dah ?
|
// }
|
||||||
keyerControl &= ~(DIT_L + DIT_PROC); // clear two bits
|
// break;
|
||||||
keyerState = CHK_DAH; // dit done, check for dah
|
//
|
||||||
}else{
|
// case INTER_ELEMENT:
|
||||||
keyerControl &= ~(DAH_L); // clear dah latch
|
// // Insert time between dits/dahs
|
||||||
keyerState = IDLE; // go idle
|
// 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 ?
|
||||||
break;
|
// keyerControl &= ~(DIT_L + DIT_PROC); // clear two bits
|
||||||
}
|
// keyerState = CHK_DAH; // dit done, check for dah
|
||||||
|
// }else{
|
||||||
Check_Cat(2);
|
// keyerControl &= ~(DAH_L); // clear dah latch
|
||||||
} //end of while
|
// keyerState = IDLE; // go idle
|
||||||
}
|
// }
|
||||||
else{
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Check_Cat(2);
|
||||||
|
// } //end of while
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
while(1){
|
while(1){
|
||||||
if (update_PaddleLatch(0) == DIT_L) {
|
if (update_PaddleLatch(0) == DIT_L) {
|
||||||
// if we are here, it is only because the key is pressed
|
// if we are here, it is only because the key is pressed
|
||||||
@@ -262,7 +298,7 @@ void cwKeyer(void){
|
|||||||
|
|
||||||
Check_Cat(2);
|
Check_Cat(2);
|
||||||
} //end of while
|
} //end of while
|
||||||
} //end of elese
|
// } //end of elese
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -365,5 +401,3 @@ void cwKeyer(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@@ -990,9 +990,17 @@ void SWS_Process(void)
|
|||||||
char checkCount = 0;
|
char checkCount = 0;
|
||||||
char checkCountSMeter = 0;
|
char checkCountSMeter = 0;
|
||||||
|
|
||||||
|
UBitxRigState rigState;
|
||||||
|
UBitxRigState catState;
|
||||||
|
|
||||||
//execute interval : 0.25sec
|
//execute interval : 0.25sec
|
||||||
void idle_process()
|
void idle_process()
|
||||||
{
|
{
|
||||||
|
// KC4UPR 2021-02-05 added update process for Raduino-TeensyDSP coordination
|
||||||
|
updateStateFromRaduino(rigState);
|
||||||
|
doRaduinoToTeensy(&rigState);
|
||||||
|
updateRaduinoFromState(rigState);
|
||||||
|
|
||||||
//S-Meter Display
|
//S-Meter Display
|
||||||
if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency))
|
if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency))
|
||||||
{
|
{
|
||||||
|
@@ -18,6 +18,8 @@ const PROGMEM uint8_t meters_bitmap[] = {
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "RigState.h"
|
||||||
|
|
||||||
//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA
|
//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA
|
||||||
|
|
||||||
#ifdef OPTION_SKINNYBARS //We want skninny bars with more text
|
#ifdef OPTION_SKINNYBARS //We want skninny bars with more text
|
||||||
@@ -296,4 +298,95 @@ int GetI2CSmeterValue(int valueType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
void doRaduinoToTeensy(UBitxRigState* r) {
|
||||||
|
uint8_t* ptr = (uint8_t*)r;
|
||||||
|
|
||||||
|
Wire.beginTransmission(I2CMETER_ADDR);
|
||||||
|
Wire.write(I2CMETER_RIGINF);
|
||||||
|
//for (size_t i = 0; i < sizeof(UBitxRigState); i++) {
|
||||||
|
// Wire.write(ptr[i]);
|
||||||
|
//}
|
||||||
|
//Note, I can switch this back...
|
||||||
|
Wire.write(ptr, sizeof(UBitxRigState));
|
||||||
|
Wire.endTransmission();
|
||||||
|
|
||||||
|
Serial.println("BEFORE:");
|
||||||
|
Serial.print("VFO A: ");
|
||||||
|
Serial.print(r->vfo[0]);
|
||||||
|
Serial.print(", VFO B: ");
|
||||||
|
Serial.print(r->vfo[1]);
|
||||||
|
Serial.print(", Data Size: ");
|
||||||
|
Serial.print(sizeof(UBitxRigState));
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
// First we need to see if there's any updated state.
|
||||||
|
Wire.requestFrom(I2CMETER_ADDR, sizeof(uint8_t));
|
||||||
|
int len = 0;
|
||||||
|
int readflag = Wire.read();
|
||||||
|
if (readflag != 0) {
|
||||||
|
Wire.requestFrom(I2CMETER_ADDR, sizeof(UBitxRigState));
|
||||||
|
|
||||||
|
UBitxRigState tmp;
|
||||||
|
|
||||||
|
//int len = 0;
|
||||||
|
//ptr = (uint8_t*)&tmp;
|
||||||
|
|
||||||
|
while (Wire.available() > 0) {
|
||||||
|
uint8_t b = Wire.read();
|
||||||
|
if (len < sizeof(UBitxRigState)) {
|
||||||
|
ptr[len++] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("AFTER:");
|
||||||
|
Serial.print("VFO A: ");
|
||||||
|
Serial.print(r->vfo[0]);
|
||||||
|
Serial.print(", VFO B: ");
|
||||||
|
Serial.print(r->vfo[1]);
|
||||||
|
Serial.print(", Data Size: ");
|
||||||
|
Serial.print(len);
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateStateFromRaduino(UBitxRigState& r) {
|
||||||
|
// Note, we really need to be checking a dirty flag for this. But, I don't have a dirty flag in this version of the data type...
|
||||||
|
if (vfoActive == VFO_A) {
|
||||||
|
rigState.vfo[0] = frequency;
|
||||||
|
rigState.flags &= ~UBITX_VFOB_FLAG;
|
||||||
|
} else if (vfoActive == VFO_B) {
|
||||||
|
rigState.vfo[1] = frequency;
|
||||||
|
rigState.flags |= UBITX_VFOB_FLAG;
|
||||||
|
}
|
||||||
|
rigState.rit = ritRxFrequency - frequency;
|
||||||
|
rigState.flags = 0;
|
||||||
|
rigState.flags |= (vfoActive == VFO_B ? UBITX_VFOB_FLAG : 0);
|
||||||
|
rigState.flags |= (cwMode != 0 ? UBITX_CW_FLAG : 0);
|
||||||
|
rigState.flags |= (isUSB != 0 ? UBITX_USB_FLAG : 0);
|
||||||
|
rigState.flags |= (splitOn != 0 ? UBITX_SPLIT_FLAG : 0);
|
||||||
|
rigState.flags |= (ritOn != 0 ? UBITX_RIT_FLAG : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateRaduinoFromState(UBitxRigState& r) {
|
||||||
|
vfoActive = rigState.flags & UBITX_VFOB_FLAG ? VFO_B : VFO_A;
|
||||||
|
if (vfoActive == VFO_A) {
|
||||||
|
if (rigState.vfo[0] != frequency) {
|
||||||
|
setFrequency(rigState.vfo[0]);
|
||||||
|
}
|
||||||
|
} else if (vfoActive == VFO_B) {
|
||||||
|
if (rigState.vfo[1] != frequency) {
|
||||||
|
setFrequency(rigState.vfo[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ritRxFrequency = frequency + rigState.rit;
|
||||||
|
splitOn = rigState.flags & UBITX_SPLIT_FLAG ? 1 : 0;
|
||||||
|
ritOn = rigState.flags & UBITX_RIT_FLAG ? 1 : 0;
|
||||||
|
isUSB = rigState.flags & UBITX_USB_FLAG ? 1 : 0;
|
||||||
|
if (rigState.flags & UBITX_CW_FLAG) {
|
||||||
|
cwMode = isUSB ? 2 : 1; // 2 = cwu / 1 = cwl
|
||||||
|
} else {
|
||||||
|
cwMode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BIN
Schematics/IO_Board-ADC_Buffer.xcf
Normal file
BIN
Schematics/IO_Board-ADC_Buffer.xcf
Normal file
Binary file not shown.
342
Schematics/IO_Board/IO_Board-cache.lib
Normal file
342
Schematics/IO_Board/IO_Board-cache.lib
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
EESchema-LIBRARY Version 2.4
|
||||||
|
#encoding utf-8
|
||||||
|
#
|
||||||
|
# Amplifier_Operational_LM324A
|
||||||
|
#
|
||||||
|
DEF Amplifier_Operational_LM324A U 0 5 Y Y 5 L N
|
||||||
|
F0 "U" 0 200 50 H V L CNN
|
||||||
|
F1 "Amplifier_Operational_LM324A" 0 -200 50 H V L CNN
|
||||||
|
F2 "" -50 100 50 H I C CNN
|
||||||
|
F3 "" 50 200 50 H I C CNN
|
||||||
|
ALIAS LM324 TLC274 TLC279 TL074 LM324A MCP6004 TL084 TL064 LMV324 LMC6484 MCP604 MC33079 MC33174 MC33179 OPA1604 OPA1679 OPA4134 OPA4340UA OPA4376 MCP6L94 TSV914 ADA4807-4 TSV994
|
||||||
|
$FPLIST
|
||||||
|
SOIC*3.9x8.7mm*P1.27mm*
|
||||||
|
DIP*W7.62mm*
|
||||||
|
TSSOP*4.4x5mm*P0.65mm*
|
||||||
|
SSOP*5.3x6.2mm*P0.65mm*
|
||||||
|
MSOP*3x3mm*P0.5mm*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
P 4 1 1 10 -200 200 200 0 -200 -200 -200 200 f
|
||||||
|
P 4 2 1 10 -200 200 200 0 -200 -200 -200 200 f
|
||||||
|
P 4 3 1 10 -200 200 200 0 -200 -200 -200 200 f
|
||||||
|
P 4 4 1 10 -200 200 200 0 -200 -200 -200 200 f
|
||||||
|
X ~ 1 300 0 100 L 50 50 1 1 O
|
||||||
|
X - 2 -300 -100 100 R 50 50 1 1 I
|
||||||
|
X + 3 -300 100 100 R 50 50 1 1 I
|
||||||
|
X + 5 -300 100 100 R 50 50 2 1 I
|
||||||
|
X - 6 -300 -100 100 R 50 50 2 1 I
|
||||||
|
X ~ 7 300 0 100 L 50 50 2 1 O
|
||||||
|
X + 10 -300 100 100 R 50 50 3 1 I
|
||||||
|
X ~ 8 300 0 100 L 50 50 3 1 O
|
||||||
|
X - 9 -300 -100 100 R 50 50 3 1 I
|
||||||
|
X + 12 -300 100 100 R 50 50 4 1 I
|
||||||
|
X - 13 -300 -100 100 R 50 50 4 1 I
|
||||||
|
X ~ 14 300 0 100 L 50 50 4 1 O
|
||||||
|
X V- 11 -100 -300 150 U 50 50 5 1 W
|
||||||
|
X V+ 4 -100 300 150 D 50 50 5 1 W
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Amplifier_Operational_LM358
|
||||||
|
#
|
||||||
|
DEF Amplifier_Operational_LM358 U 0 5 Y Y 3 L N
|
||||||
|
F0 "U" 0 200 50 H V L CNN
|
||||||
|
F1 "Amplifier_Operational_LM358" 0 -200 50 H V L CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
SOIC*3.9x4.9mm*P1.27mm*
|
||||||
|
DIP*W7.62mm*
|
||||||
|
TO*99*
|
||||||
|
OnSemi*Micro8*
|
||||||
|
TSSOP*3x3mm*P0.65mm*
|
||||||
|
TSSOP*4.4x3mm*P0.65mm*
|
||||||
|
MSOP*3x3mm*P0.65mm*
|
||||||
|
SSOP*3.9x4.9mm*P0.635mm*
|
||||||
|
LFCSP*2x2mm*P0.5mm*
|
||||||
|
*SIP*
|
||||||
|
SOIC*5.3x6.2mm*P1.27mm*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
P 4 1 1 10 -200 200 200 0 -200 -200 -200 200 f
|
||||||
|
P 4 2 1 10 -200 200 200 0 -200 -200 -200 200 f
|
||||||
|
X ~ 1 300 0 100 L 50 50 1 1 O
|
||||||
|
X - 2 -300 -100 100 R 50 50 1 1 I
|
||||||
|
X + 3 -300 100 100 R 50 50 1 1 I
|
||||||
|
X + 5 -300 100 100 R 50 50 2 1 I
|
||||||
|
X - 6 -300 -100 100 R 50 50 2 1 I
|
||||||
|
X ~ 7 300 0 100 L 50 50 2 1 O
|
||||||
|
X V- 4 -100 -300 150 U 50 50 3 1 W
|
||||||
|
X V+ 8 -100 300 150 D 50 50 3 1 W
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Amplifier_Operational_TL072
|
||||||
|
#
|
||||||
|
DEF Amplifier_Operational_TL072 U 0 5 Y Y 3 L N
|
||||||
|
F0 "U" 0 200 50 H V L CNN
|
||||||
|
F1 "Amplifier_Operational_TL072" 0 -200 50 H V L CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
ALIAS LM358 AD8620 LMC6062 LMC6082 TL062 TL072 TL082 NE5532 SA5532 RC4558 RC4560 RC4580 LMV358 TS912 TSV912IDT TSV912IST TLC272 TLC277 MCP602 OPA1678 OPA2134 OPA2340 OPA2376xxD OPA2376xxDGK MC33078 MC33178 LM4562 OP249 OP275 ADA4075-2 MCP6002-xP MCP6002-xSN MCP6002-xMS LM7332 OPA2333xxD OPA2333xxDGK LMC6482 LT1492 LTC6081xMS8 LM6172 MCP6L92 NJM2043 NJM2114 NJM4556A NJM4558 NJM4559 NJM4560 NJM4580 NJM5532 ADA4807-2ARM OPA2691 LT6234 OPA2356xxD OPA2356xxDGK OPA1612AxD MC33172 OPA1602 TLV2372 LT6237 OPA2277
|
||||||
|
$FPLIST
|
||||||
|
SOIC*3.9x4.9mm*P1.27mm*
|
||||||
|
DIP*W7.62mm*
|
||||||
|
TO*99*
|
||||||
|
OnSemi*Micro8*
|
||||||
|
TSSOP*3x3mm*P0.65mm*
|
||||||
|
TSSOP*4.4x3mm*P0.65mm*
|
||||||
|
MSOP*3x3mm*P0.65mm*
|
||||||
|
SSOP*3.9x4.9mm*P0.635mm*
|
||||||
|
LFCSP*2x2mm*P0.5mm*
|
||||||
|
*SIP*
|
||||||
|
SOIC*5.3x6.2mm*P1.27mm*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
P 4 1 1 10 -200 200 200 0 -200 -200 -200 200 f
|
||||||
|
P 4 2 1 10 -200 200 200 0 -200 -200 -200 200 f
|
||||||
|
X ~ 1 300 0 100 L 50 50 1 1 O
|
||||||
|
X - 2 -300 -100 100 R 50 50 1 1 I
|
||||||
|
X + 3 -300 100 100 R 50 50 1 1 I
|
||||||
|
X + 5 -300 100 100 R 50 50 2 1 I
|
||||||
|
X - 6 -300 -100 100 R 50 50 2 1 I
|
||||||
|
X ~ 7 300 0 100 L 50 50 2 1 O
|
||||||
|
X V- 4 -100 -300 150 U 50 50 3 1 W
|
||||||
|
X V+ 8 -100 300 150 D 50 50 3 1 W
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Connector_Conn_01x02_Male
|
||||||
|
#
|
||||||
|
DEF Connector_Conn_01x02_Male J 0 40 Y N 1 F N
|
||||||
|
F0 "J" 0 100 50 H V C CNN
|
||||||
|
F1 "Connector_Conn_01x02_Male" 0 -200 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
Connector*:*_1x??_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
S 34 -95 0 -105 1 1 6 F
|
||||||
|
S 34 5 0 -5 1 1 6 F
|
||||||
|
P 2 1 1 6 50 -100 34 -100 N
|
||||||
|
P 2 1 1 6 50 0 34 0 N
|
||||||
|
X Pin_1 1 200 0 150 L 50 50 1 1 P
|
||||||
|
X Pin_2 2 200 -100 150 L 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Connector_Conn_01x03_Male
|
||||||
|
#
|
||||||
|
DEF Connector_Conn_01x03_Male J 0 40 Y N 1 F N
|
||||||
|
F0 "J" 0 200 50 H V C CNN
|
||||||
|
F1 "Connector_Conn_01x03_Male" 0 -200 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
Connector*:*_1x??_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
S 34 -95 0 -105 1 1 6 F
|
||||||
|
S 34 5 0 -5 1 1 6 F
|
||||||
|
S 34 105 0 95 1 1 6 F
|
||||||
|
P 2 1 1 6 50 -100 34 -100 N
|
||||||
|
P 2 1 1 6 50 0 34 0 N
|
||||||
|
P 2 1 1 6 50 100 34 100 N
|
||||||
|
X Pin_1 1 200 100 150 L 50 50 1 1 P
|
||||||
|
X Pin_2 2 200 0 150 L 50 50 1 1 P
|
||||||
|
X Pin_3 3 200 -100 150 L 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Connector_Conn_01x06_Male
|
||||||
|
#
|
||||||
|
DEF Connector_Conn_01x06_Male J 0 40 Y N 1 F N
|
||||||
|
F0 "J" 0 300 50 H V C CNN
|
||||||
|
F1 "Connector_Conn_01x06_Male" 0 -400 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
Connector*:*_1x??_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
S 34 -295 0 -305 1 1 6 F
|
||||||
|
S 34 -195 0 -205 1 1 6 F
|
||||||
|
S 34 -95 0 -105 1 1 6 F
|
||||||
|
S 34 5 0 -5 1 1 6 F
|
||||||
|
S 34 105 0 95 1 1 6 F
|
||||||
|
S 34 205 0 195 1 1 6 F
|
||||||
|
P 2 1 1 6 50 -300 34 -300 N
|
||||||
|
P 2 1 1 6 50 -200 34 -200 N
|
||||||
|
P 2 1 1 6 50 -100 34 -100 N
|
||||||
|
P 2 1 1 6 50 0 34 0 N
|
||||||
|
P 2 1 1 6 50 100 34 100 N
|
||||||
|
P 2 1 1 6 50 200 34 200 N
|
||||||
|
X Pin_1 1 200 200 150 L 50 50 1 1 P
|
||||||
|
X Pin_2 2 200 100 150 L 50 50 1 1 P
|
||||||
|
X Pin_3 3 200 0 150 L 50 50 1 1 P
|
||||||
|
X Pin_4 4 200 -100 150 L 50 50 1 1 P
|
||||||
|
X Pin_5 5 200 -200 150 L 50 50 1 1 P
|
||||||
|
X Pin_6 6 200 -300 150 L 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Device_C
|
||||||
|
#
|
||||||
|
DEF Device_C C 0 10 N Y 1 F N
|
||||||
|
F0 "C" 25 100 50 H V L CNN
|
||||||
|
F1 "Device_C" 25 -100 50 H V L CNN
|
||||||
|
F2 "" 38 -150 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
C_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
P 2 0 1 20 -80 -30 80 -30 N
|
||||||
|
P 2 0 1 20 -80 30 80 30 N
|
||||||
|
X ~ 1 0 150 110 D 50 50 1 1 P
|
||||||
|
X ~ 2 0 -150 110 U 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Device_CP1
|
||||||
|
#
|
||||||
|
DEF Device_CP1 C 0 10 N N 1 F N
|
||||||
|
F0 "C" 25 100 50 H V L CNN
|
||||||
|
F1 "Device_CP1" 25 -100 50 H V L CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
CP_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
A 0 -150 128 1287 513 0 1 20 N -80 -50 80 -50
|
||||||
|
P 2 0 1 20 -80 30 80 30 N
|
||||||
|
P 2 0 1 0 -70 90 -30 90 N
|
||||||
|
P 2 0 1 0 -50 70 -50 110 N
|
||||||
|
X ~ 1 0 150 110 D 50 50 1 1 P
|
||||||
|
X ~ 2 0 -150 130 U 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Device_D
|
||||||
|
#
|
||||||
|
DEF Device_D D 0 40 N N 1 F N
|
||||||
|
F0 "D" 0 100 50 H V C CNN
|
||||||
|
F1 "Device_D" 0 -100 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
TO-???*
|
||||||
|
*_Diode_*
|
||||||
|
*SingleDiode*
|
||||||
|
D_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
P 2 0 1 8 -50 50 -50 -50 N
|
||||||
|
P 2 0 1 0 50 0 -50 0 N
|
||||||
|
P 4 0 1 8 50 50 50 -50 -50 0 50 50 N
|
||||||
|
X K 1 -150 0 100 R 50 50 1 1 P
|
||||||
|
X A 2 150 0 100 L 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Device_R_POT_US
|
||||||
|
#
|
||||||
|
DEF Device_R_POT_US RV 0 40 Y N 1 F N
|
||||||
|
F0 "RV" -175 0 50 V V C CNN
|
||||||
|
F1 "Device_R_POT_US" -100 0 50 V V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
Potentiometer*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
P 2 0 1 0 0 -90 0 -100 N
|
||||||
|
P 2 0 1 0 0 100 0 90 N
|
||||||
|
P 2 0 1 0 100 0 60 0 N
|
||||||
|
P 4 0 1 0 45 0 90 20 90 -20 45 0 F
|
||||||
|
P 5 0 1 0 0 -30 40 -45 0 -60 -40 -75 0 -90 N
|
||||||
|
P 5 0 1 0 0 30 40 15 0 0 -40 -15 0 -30 N
|
||||||
|
P 5 0 1 0 0 90 40 75 0 60 -40 45 0 30 N
|
||||||
|
X 1 1 0 150 50 D 50 50 1 1 P
|
||||||
|
X 2 2 150 0 50 L 50 50 1 1 P
|
||||||
|
X 3 3 0 -150 50 U 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Device_R_US
|
||||||
|
#
|
||||||
|
DEF Device_R_US R 0 0 N Y 1 F N
|
||||||
|
F0 "R" 100 0 50 V V C CNN
|
||||||
|
F1 "Device_R_US" -100 0 50 V V C CNN
|
||||||
|
F2 "" 40 -10 50 V I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
R_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
P 2 0 1 0 0 -90 0 -100 N
|
||||||
|
P 2 0 1 0 0 90 0 100 N
|
||||||
|
P 5 0 1 0 0 -30 40 -45 0 -60 -40 -75 0 -90 N
|
||||||
|
P 5 0 1 0 0 30 40 15 0 0 -40 -15 0 -30 N
|
||||||
|
P 5 0 1 0 0 90 40 75 0 60 -40 45 0 30 N
|
||||||
|
X ~ 1 0 150 50 D 50 50 1 1 P
|
||||||
|
X ~ 2 0 -150 50 U 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Transistor_BJT_PN2222A
|
||||||
|
#
|
||||||
|
DEF Transistor_BJT_PN2222A Q 0 0 Y N 1 F N
|
||||||
|
F0 "Q" 200 75 50 H V L CNN
|
||||||
|
F1 "Transistor_BJT_PN2222A" 200 0 50 H V L CNN
|
||||||
|
F2 "Package_TO_SOT_THT:TO-92_Inline" 200 -75 50 H I L CIN
|
||||||
|
F3 "" 0 0 50 H I L CNN
|
||||||
|
$FPLIST
|
||||||
|
TO?92*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
C 50 0 111 0 1 10 N
|
||||||
|
P 2 0 1 0 0 0 25 0 N
|
||||||
|
P 2 0 1 0 100 -100 25 -25 N
|
||||||
|
P 2 0 1 0 100 100 25 25 N
|
||||||
|
P 3 0 1 20 25 75 25 -75 25 -75 N
|
||||||
|
P 3 0 1 0 95 -95 75 -75 75 -75 N
|
||||||
|
P 5 0 1 0 45 -65 65 -45 85 -85 45 -65 45 -65 F
|
||||||
|
X E 1 100 -200 100 U 50 50 1 1 P
|
||||||
|
X B 2 -200 0 200 R 50 50 1 1 I
|
||||||
|
X C 3 100 200 100 D 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# power_+5V
|
||||||
|
#
|
||||||
|
DEF power_+5V #PWR 0 0 Y Y 1 F P
|
||||||
|
F0 "#PWR" 0 -150 50 H I C CNN
|
||||||
|
F1 "power_+5V" 0 140 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
DRAW
|
||||||
|
P 2 0 1 0 -30 50 0 100 N
|
||||||
|
P 2 0 1 0 0 0 0 100 N
|
||||||
|
P 2 0 1 0 0 100 30 50 N
|
||||||
|
X +5V 1 0 0 0 U 50 50 1 1 W N
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# power_GND
|
||||||
|
#
|
||||||
|
DEF power_GND #PWR 0 0 Y Y 1 F P
|
||||||
|
F0 "#PWR" 0 -250 50 H I C CNN
|
||||||
|
F1 "power_GND" 0 -150 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
DRAW
|
||||||
|
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
|
||||||
|
X GND 1 0 0 0 D 50 50 1 1 W N
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
#End Library
|
1
Schematics/IO_Board/IO_Board.kicad_pcb
Normal file
1
Schematics/IO_Board/IO_Board.kicad_pcb
Normal file
@@ -0,0 +1 @@
|
|||||||
|
(kicad_pcb (version 4) (host kicad "dummy file") )
|
33
Schematics/IO_Board/IO_Board.pro
Normal file
33
Schematics/IO_Board/IO_Board.pro
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
update=22/05/2015 07:44:53
|
||||||
|
version=1
|
||||||
|
last_client=kicad
|
||||||
|
[general]
|
||||||
|
version=1
|
||||||
|
RootSch=
|
||||||
|
BoardNm=
|
||||||
|
[pcbnew]
|
||||||
|
version=1
|
||||||
|
LastNetListRead=
|
||||||
|
UseCmpFile=1
|
||||||
|
PadDrill=0.600000000000
|
||||||
|
PadDrillOvalY=0.600000000000
|
||||||
|
PadSizeH=1.500000000000
|
||||||
|
PadSizeV=1.500000000000
|
||||||
|
PcbTextSizeV=1.500000000000
|
||||||
|
PcbTextSizeH=1.500000000000
|
||||||
|
PcbTextThickness=0.300000000000
|
||||||
|
ModuleTextSizeV=1.000000000000
|
||||||
|
ModuleTextSizeH=1.000000000000
|
||||||
|
ModuleTextSizeThickness=0.150000000000
|
||||||
|
SolderMaskClearance=0.000000000000
|
||||||
|
SolderMaskMinWidth=0.000000000000
|
||||||
|
DrawSegmentWidth=0.200000000000
|
||||||
|
BoardOutlineThickness=0.100000000000
|
||||||
|
ModuleOutlineThickness=0.150000000000
|
||||||
|
[cvpcb]
|
||||||
|
version=1
|
||||||
|
NetIExt=net
|
||||||
|
[eeschema]
|
||||||
|
version=1
|
||||||
|
LibDir=
|
||||||
|
[eeschema/libraries]
|
1111
Schematics/IO_Board/IO_Board.sch
Normal file
1111
Schematics/IO_Board/IO_Board.sch
Normal file
File diff suppressed because it is too large
Load Diff
1105
Schematics/IO_Board/IO_Board.sch-bak
Normal file
1105
Schematics/IO_Board/IO_Board.sch-bak
Normal file
File diff suppressed because it is too large
Load Diff
16
Schematics/IO_Board/IO_Board_Wiring.sch
Normal file
16
Schematics/IO_Board/IO_Board_Wiring.sch
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
EESchema Schematic File Version 4
|
||||||
|
EELAYER 30 0
|
||||||
|
EELAYER END
|
||||||
|
$Descr A4 11693 8268
|
||||||
|
encoding utf-8
|
||||||
|
Sheet 2 2
|
||||||
|
Title ""
|
||||||
|
Date ""
|
||||||
|
Rev ""
|
||||||
|
Comp ""
|
||||||
|
Comment1 ""
|
||||||
|
Comment2 ""
|
||||||
|
Comment3 ""
|
||||||
|
Comment4 ""
|
||||||
|
$EndDescr
|
||||||
|
$EndSCHEMATC
|
@@ -22,30 +22,28 @@ UBitxDSP DSP;
|
|||||||
|
|
||||||
//static struct {
|
//static struct {
|
||||||
|
|
||||||
// GUItool: begin automatically generated code
|
// GUItool: begin automatically generated code
|
||||||
AudioInputI2S lineIn; //xy=137,220
|
AudioInputI2S lineIn; //xy=385.9371643066406,1001.9600830078125
|
||||||
AudioInputUSB usbIn; //xy=142,326
|
AudioInputUSB usbIn; //xy=390.9371643066406,1107.9600830078125
|
||||||
AudioMixer4 rxAudio; //xy=394,134
|
AudioMixer4 rxAudio; //xy=642.9371643066406,915.9600830078125
|
||||||
AudioMixer4 txAudio; //xy=398,322
|
AudioMixer4 txAudio; //xy=646.9371643066406,1103.9600830078125
|
||||||
AudioOutputAnalog spkrOut; //xy=774,104
|
AudioOutputUSB usbOut; //xy=1022.9371643066406,919.9600830078125
|
||||||
AudioOutputUSB usbOut; //xy=774,138
|
AudioOutputI2S lineOut; //xy=1024.9371643066406,1017.9600830078125
|
||||||
AudioOutputI2S lineOut; //xy=776,236
|
AudioConnection patchCord1(lineIn, 0, rxAudio, 0);
|
||||||
AudioConnection patchCord1(lineIn, 0, rxAudio, 0);
|
AudioConnection patchCord2(lineIn, 1, txAudio, 0);
|
||||||
AudioConnection patchCord2(lineIn, 1, txAudio, 0);
|
AudioConnection patchCord3(usbIn, 0, txAudio, 1);
|
||||||
AudioConnection patchCord3(usbIn, 0, txAudio, 1);
|
AudioConnection patchCord4(usbIn, 1, txAudio, 2);
|
||||||
AudioConnection patchCord4(usbIn, 1, txAudio, 2);
|
AudioConnection patchCord5(rxAudio, 0, lineOut, 0);
|
||||||
AudioConnection patchCord5(rxAudio, spkrOut);
|
AudioConnection patchCord6(rxAudio, 0, usbOut, 0);
|
||||||
AudioConnection patchCord6(rxAudio, 0, lineOut, 0);
|
AudioConnection patchCord7(rxAudio, 0, usbOut, 1);
|
||||||
AudioConnection patchCord7(rxAudio, 0, usbOut, 0);
|
AudioConnection patchCord8(txAudio, 0, lineOut, 1);
|
||||||
AudioConnection patchCord8(rxAudio, 0, usbOut, 1);
|
AudioControlSGTL5000 audioCtrl; //xy=651.9371643066406,1244.9600830078125
|
||||||
AudioConnection patchCord9(txAudio, 0, lineOut, 1);
|
// GUItool: end automatically generated code
|
||||||
AudioControlSGTL5000 audioCtrl; //xy=403,463
|
|
||||||
// GUItool: end automatically generated code
|
|
||||||
|
|
||||||
//} audio;
|
//} audio;
|
||||||
|
|
||||||
void UBitxDSP::begin() {
|
void UBitxDSP::begin() {
|
||||||
AudioMemory(20);
|
AudioMemory(16);
|
||||||
audioCtrl.enable();
|
audioCtrl.enable();
|
||||||
audioCtrl.volume(0.0); // headphone volume...
|
audioCtrl.volume(0.0); // headphone volume...
|
||||||
audioCtrl.muteHeadphone(); // ...not used by UBitxDSP
|
audioCtrl.muteHeadphone(); // ...not used by UBitxDSP
|
||||||
@@ -66,8 +64,8 @@ void UBitxDSP::begin() {
|
|||||||
// Rig (Line) Input (RX)
|
// Rig (Line) Input (RX)
|
||||||
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
|
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
|
||||||
audioCtrl.unmuteLineout();
|
audioCtrl.unmuteLineout();
|
||||||
audioCtrl.lineInLevel(5, 5); // RX, TX
|
audioCtrl.lineInLevel(9, 5); // RX, TX
|
||||||
audioCtrl.lineOutLevel(29, 29); //RX, TX
|
audioCtrl.lineOutLevel(29, 31); //RX, TX
|
||||||
|
|
||||||
// Mic Input (TX)
|
// Mic Input (TX)
|
||||||
audioCtrl.micGain(0); // TODO: set value
|
audioCtrl.micGain(0); // TODO: set value
|
||||||
@@ -78,9 +76,6 @@ void UBitxDSP::begin() {
|
|||||||
|
|
||||||
// SETUP THE AUDIO OUTPUTS
|
// SETUP THE AUDIO OUTPUTS
|
||||||
|
|
||||||
// Speaker Output (RX)
|
|
||||||
spkrOut.analogReference(INTERNAL);
|
|
||||||
|
|
||||||
// Line Output (RX)
|
// Line Output (RX)
|
||||||
|
|
||||||
// USB Output (RX)
|
// USB Output (RX)
|
||||||
@@ -91,11 +86,16 @@ void UBitxDSP::begin() {
|
|||||||
rx();
|
rx();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UBitxDSP::update() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void UBitxDSP::end() {
|
void UBitxDSP::end() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UBitxDSP::rx() {
|
void UBitxDSP::rx() {
|
||||||
// mute all tx audio
|
// mute all tx audio
|
||||||
|
audioCtrl.micGain(0);
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
txAudio.gain(i, 0.0);
|
txAudio.gain(i, 0.0);
|
||||||
}
|
}
|
||||||
@@ -110,9 +110,10 @@ void UBitxDSP::txMicIn() {
|
|||||||
rxAudio.gain(RX_AUDIO_CH, 0.0);
|
rxAudio.gain(RX_AUDIO_CH, 0.0);
|
||||||
// restore the tx mic audio
|
// restore the tx mic audio
|
||||||
audioCtrl.inputSelect(AUDIO_INPUT_MIC);
|
audioCtrl.inputSelect(AUDIO_INPUT_MIC);
|
||||||
|
audioCtrl.micGain(12);
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (i == TX_MIC_IN_CH)
|
if (i == TX_MIC_IN_CH)
|
||||||
txAudio.gain(i, 1.0);
|
txAudio.gain(i, 0.1);
|
||||||
else
|
else
|
||||||
txAudio.gain(i, 0.0);
|
txAudio.gain(i, 0.0);
|
||||||
}
|
}
|
||||||
@@ -125,7 +126,7 @@ void UBitxDSP::txLineIn() {
|
|||||||
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
|
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (i == TX_LINE_IN_CH)
|
if (i == TX_LINE_IN_CH)
|
||||||
txAudio.gain(i, 1.0);
|
txAudio.gain(i, 0.1);
|
||||||
else
|
else
|
||||||
txAudio.gain(i, 0.0);
|
txAudio.gain(i, 0.0);
|
||||||
}
|
}
|
||||||
@@ -138,7 +139,7 @@ void UBitxDSP::txUSBIn() {
|
|||||||
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
|
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (i == TX_USB_IN_CH1 || i == TX_USB_IN_CH2)
|
if (i == TX_USB_IN_CH1 || i == TX_USB_IN_CH2)
|
||||||
txAudio.gain(i, 1.0);
|
txAudio.gain(i, 0.1);
|
||||||
else
|
else
|
||||||
txAudio.gain(i, 0.0);
|
txAudio.gain(i, 0.0);
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,7 @@ class UBitxDSP {
|
|||||||
public:
|
public:
|
||||||
UBitxDSP() {};
|
UBitxDSP() {};
|
||||||
void begin();
|
void begin();
|
||||||
|
void update();
|
||||||
void end();
|
void end();
|
||||||
void rx();
|
void rx();
|
||||||
void txMicIn();
|
void txMicIn();
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
#define DBGPRINT(MSG) do { Serial.print("DBG: "); Serial.print(MSG); } while (0)
|
#define DBGPRINT(MSG) do { Serial.print("DBG: "); Serial.print(MSG); } while (0)
|
||||||
#define DBGPRINTLN(MSG) do { Serial.print("DBG: "); Serial.println(MSG); } while (0)
|
#define DBGPRINTLN(MSG) do { Serial.print("DBG: "); Serial.println(MSG); } while (0)
|
||||||
#define DBGNEWLINE() do { Serial.println(); } while (0)
|
#define DBGNEWLINE() do { Serial.println(); } while (0)
|
||||||
#define DBGCMD(CMD) do { Serial.println("DBG: "); Serial.println(#CMD); CMD; } while (0)
|
#define DBGCMD(CMD) do { Serial.print("DBG: "); Serial.println(#CMD); CMD; } while (0)
|
||||||
#else
|
#else
|
||||||
#define DBGPRINT(MSG) do {} while (0)
|
#define DBGPRINT(MSG) do {} while (0)
|
||||||
#define DBGPRINTLN(MSG) do {} while (0)
|
#define DBGPRINTLN(MSG) do {} while (0)
|
||||||
|
185
TeensyDSP/Keyer.cpp
Normal file
185
TeensyDSP/Keyer.cpp
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
//======================================================================
|
||||||
|
//
|
||||||
|
// nanoIO paddle keyer (c) 2018, David Freese, W1HKJ
|
||||||
|
//
|
||||||
|
// based on code from Iambic Keyer Code Keyer Sketch
|
||||||
|
// Copyright (c) 2009 Steven T. Elliott
|
||||||
|
//
|
||||||
|
// 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:
|
||||||
|
//
|
||||||
|
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
// Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
//#include "TimerOne.h"
|
||||||
|
//#include "config.h"
|
||||||
|
#include "Keyer.h"
|
||||||
|
|
||||||
|
const uint8_t LP_in = KEYER_LEFT_PADDLE_PIN;
|
||||||
|
const uint8_t RP_in = KEYER_RIGHT_PADDLE_PIN;
|
||||||
|
|
||||||
|
//#define ST_Freq 600 // Set the Sidetone Frequency to 600 Hz
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// keyerControl bit definitions
|
||||||
|
//
|
||||||
|
#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
|
||||||
|
//======================================================================
|
||||||
|
//
|
||||||
|
// State Machine Defines
|
||||||
|
|
||||||
|
enum KSTYPE { IDLE, CHK_DIT, CHK_DAH, KEYED_PREP, KEYED, INTER_ELEMENT };
|
||||||
|
|
||||||
|
UBitxKeyer::UBitxKeyer(int wpm, float weight):
|
||||||
|
speed(wpm), symWeight(weight)
|
||||||
|
{
|
||||||
|
// Setup outputs
|
||||||
|
pinMode(LP_in, INPUT_PULLUP); // sets Left Paddle digital pin as input
|
||||||
|
pinMode(RP_in, INPUT_PULLUP); // sets Right Paddle digital pin as input
|
||||||
|
|
||||||
|
keyerState = IDLE;
|
||||||
|
keyerControl = 0;
|
||||||
|
keyMode = IAMBICA;
|
||||||
|
keyDown = false;
|
||||||
|
|
||||||
|
calcRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the length of dot, dash and silence
|
||||||
|
void UBitxKeyer::calcRatio()
|
||||||
|
{
|
||||||
|
float w = (1 + symWeight) / (symWeight -1);
|
||||||
|
spaceLen = (1200 / speed);
|
||||||
|
dotLen = spaceLen * (w - 1);
|
||||||
|
dashLen = (1 + w) * spaceLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UBitxKeyer::setWPM(int wpm)
|
||||||
|
{
|
||||||
|
speed = wpm;
|
||||||
|
calcRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// Latch paddle press
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
void UBitxKeyer::updatePaddleLatch()
|
||||||
|
{
|
||||||
|
if (digitalRead(LP_in) == LOW) {
|
||||||
|
keyerControl |= DIT_L;
|
||||||
|
}
|
||||||
|
if (digitalRead(RP_in) == LOW) {
|
||||||
|
keyerControl |= DAH_L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UBitxKeyer::doPaddles()
|
||||||
|
{
|
||||||
|
if (keyMode == STRAIGHT) { // Straight Key
|
||||||
|
if ((digitalRead(LP_in) == LOW) || (digitalRead(RP_in) == LOW)) {
|
||||||
|
keyDown = true;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
keyDown = false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// keyerControl contains processing flags and keyer mode bits
|
||||||
|
// Supports Iambic A and B
|
||||||
|
// State machine based, uses calls to millis() for timing.
|
||||||
|
switch (keyerState) {
|
||||||
|
case IDLE: // Wait for direct or latched paddle press
|
||||||
|
if ((digitalRead(LP_in) == LOW) || (digitalRead(RP_in) == LOW) || (keyerControl & 0x03)) {
|
||||||
|
updatePaddleLatch();
|
||||||
|
keyerState = CHK_DIT;
|
||||||
|
// letting this fall through // return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// break;
|
||||||
|
|
||||||
|
case CHK_DIT: // See if the dit paddle was pressed
|
||||||
|
if (keyerControl & DIT_L) {
|
||||||
|
keyerControl |= DIT_PROC;
|
||||||
|
ktimer = dotLen;
|
||||||
|
keyerState = KEYED_PREP;
|
||||||
|
return true;
|
||||||
|
} else { // fall through
|
||||||
|
keyerState = CHK_DAH;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CHK_DAH: // See if dah paddle was pressed
|
||||||
|
if (keyerControl & DAH_L) {
|
||||||
|
ktimer = dashLen;
|
||||||
|
keyerState = KEYED_PREP;
|
||||||
|
// letting this fall through // return true;
|
||||||
|
} else {
|
||||||
|
keyerState = IDLE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// break;
|
||||||
|
|
||||||
|
case KEYED_PREP: // Assert key down, start timing
|
||||||
|
// state shared for dit or dah
|
||||||
|
keyDown = true;
|
||||||
|
ktimer += millis(); // set ktimer to interval end time
|
||||||
|
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
||||||
|
keyerState = KEYED; // next state
|
||||||
|
// letting this fall through // return true;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
case KEYED: // Wait for timer to expire
|
||||||
|
if (millis() > ktimer) { // are we at end of key down ?
|
||||||
|
keyDown = false;
|
||||||
|
ktimer = millis() + spaceLen; // inter-element time
|
||||||
|
keyerState = INTER_ELEMENT; // next state
|
||||||
|
// letting this fall through // return true;
|
||||||
|
} else if (keyMode == IAMBICB) { // Iambic B Mode ?
|
||||||
|
updatePaddleLatch(); // yes, early paddle latch in Iambic B mode
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// break;
|
||||||
|
|
||||||
|
case INTER_ELEMENT: // Insert time between dits/dahs
|
||||||
|
updatePaddleLatch(); // 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
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
keyerControl &= ~(DAH_L); // clear dah latch
|
||||||
|
keyerState = IDLE; // go idle
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // resolve compiler warning; do we ever get here?
|
||||||
|
}
|
||||||
|
|
||||||
|
UBitxKeyer basicKeyer(15, 3.0);
|
||||||
|
UBitxKeyer& Keyer = basicKeyer;
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// EOF
|
||||||
|
//======================================================================
|
79
TeensyDSP/Keyer.h
Normal file
79
TeensyDSP/Keyer.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
//**********************************************************************
|
||||||
|
//
|
||||||
|
// Keyer, a part of nanoIO
|
||||||
|
//
|
||||||
|
// nanoIO paddle keyer (c) 2018, David Freese, W1HKJ
|
||||||
|
//
|
||||||
|
// based on code from Iambic Keyer Code Keyer Sketch
|
||||||
|
// Copyright (c) 2009 Steven T. Elliott
|
||||||
|
//
|
||||||
|
// nanoIO 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.
|
||||||
|
//
|
||||||
|
// nanoIO 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 fldigi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
//Revisions:
|
||||||
|
//
|
||||||
|
//1.0.0: Initial release
|
||||||
|
//
|
||||||
|
//**********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __Keyer_h__
|
||||||
|
#define __Keyer_h__
|
||||||
|
|
||||||
|
#define IAMBICA 0
|
||||||
|
#define IAMBICB 1
|
||||||
|
#define STRAIGHT 2
|
||||||
|
|
||||||
|
#define KEYER_LEFT_PADDLE_PIN 17
|
||||||
|
#define KEYER_RIGHT_PADDLE_PIN 16
|
||||||
|
|
||||||
|
class UBitxKeyer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UBitxKeyer(int wpm, float weight);
|
||||||
|
//void cw_pin(int pin);
|
||||||
|
//void ptt_pin(int pin);
|
||||||
|
void setWPM(int wpm);
|
||||||
|
inline void setMode(int mode) { keyMode = mode; }
|
||||||
|
inline int getMode() { return keyMode; }
|
||||||
|
inline bool isDown() { return keyDown; }
|
||||||
|
// void setWeight();
|
||||||
|
|
||||||
|
bool doPaddles();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calcRatio();
|
||||||
|
void updatePaddleLatch();
|
||||||
|
|
||||||
|
bool keyDown;
|
||||||
|
|
||||||
|
long ktimer;
|
||||||
|
|
||||||
|
int speed;
|
||||||
|
int dashLen; // Length of dash
|
||||||
|
int dotLen; // Length of dot
|
||||||
|
int spaceLen; // Length of space
|
||||||
|
float symWeight;
|
||||||
|
|
||||||
|
char keyerControl;
|
||||||
|
char keyerState;
|
||||||
|
int keyMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern UBitxKeyer& Keyer;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// EOF
|
||||||
|
//======================================================================
|
@@ -30,10 +30,10 @@ float calcVSWR = 0.0;
|
|||||||
float L_calcVSWR = 0.0;
|
float L_calcVSWR = 0.0;
|
||||||
byte scaledVSWR = 0;
|
byte scaledVSWR = 0;
|
||||||
byte L_scaledVSWR = 0;
|
byte L_scaledVSWR = 0;
|
||||||
int fwdPower = 0;
|
float fwdPower = 0;
|
||||||
int L_fwdPower = 0;
|
float L_fwdPower = 0;
|
||||||
int revPower = 0;
|
float revPower = 0;
|
||||||
int L_revPower = 0;
|
float L_revPower = 0;
|
||||||
|
|
||||||
|
|
||||||
//Control must have prefix 'v' or 's'
|
//Control must have prefix 'v' or 's'
|
||||||
|
@@ -107,11 +107,11 @@ extern float L_calcVSWR;
|
|||||||
extern byte scaledVSWR;
|
extern byte scaledVSWR;
|
||||||
extern byte L_scaledVSWR;
|
extern byte L_scaledVSWR;
|
||||||
|
|
||||||
extern int fwdPower;
|
extern float fwdPower;
|
||||||
extern int L_fwdPower;
|
extern float L_fwdPower;
|
||||||
|
|
||||||
extern int revPower;
|
extern float revPower;
|
||||||
extern int L_revPower;
|
extern float L_revPower;
|
||||||
|
|
||||||
void sendHeader(char varType, char varIndex);
|
void sendHeader(char varType, char varIndex);
|
||||||
void sendCommandUL(char varIndex, unsigned long sendValue);
|
void sendCommandUL(char varIndex, unsigned long sendValue);
|
||||||
|
3
TeensyDSP/Rig.cpp
Normal file
3
TeensyDSP/Rig.cpp
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#include "Rig.h"
|
||||||
|
|
||||||
|
UBitxRig Rig;
|
147
TeensyDSP/Rig.h
Normal file
147
TeensyDSP/Rig.h
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
#ifndef __Rig_h__
|
||||||
|
#define __Rig_h__
|
||||||
|
|
||||||
|
#include "RigState.h"
|
||||||
|
|
||||||
|
enum UpdateSource {
|
||||||
|
NoSource,
|
||||||
|
RaduinoSource,
|
||||||
|
CATSource
|
||||||
|
};
|
||||||
|
|
||||||
|
class UBitxRig {
|
||||||
|
public:
|
||||||
|
inline void begin() {}
|
||||||
|
inline void update() {}
|
||||||
|
inline unsigned long getFreqA() const { return state.vfo[0]; }
|
||||||
|
inline unsigned long getFreqB() const { return state.vfo[1]; }
|
||||||
|
inline long getRIT() const { return state.rit; }
|
||||||
|
inline long getXIT() const { return state.xit; }
|
||||||
|
inline bool isVFOA() const { return (state.flags & UBITX_VFOB_FLAG) != UBITX_VFOB_FLAG; }
|
||||||
|
inline bool isVFOB() const { return (state.flags & UBITX_VFOB_FLAG) == UBITX_VFOB_FLAG; }
|
||||||
|
inline bool isSplit() const { return (state.flags & UBITX_SPLIT_FLAG) == UBITX_SPLIT_FLAG; }
|
||||||
|
inline bool isRITOn() const { return (state.flags & UBITX_RIT_FLAG) == UBITX_RIT_FLAG; }
|
||||||
|
inline bool isXITOn() const { return (state.flags & UBITX_XIT_FLAG) == UBITX_XIT_FLAG; }
|
||||||
|
inline bool isCW() const { return (state.flags & UBITX_CW_FLAG) == UBITX_CW_FLAG; }
|
||||||
|
inline bool isLSB() const { return (state.flags & UBITX_USB_FLAG) != UBITX_USB_FLAG; }
|
||||||
|
inline bool isUSB() const { return (state.flags & UBITX_USB_FLAG) == UBITX_USB_FLAG; }
|
||||||
|
inline bool getAI() const { return autoInfo; }
|
||||||
|
inline bool updatedByCAT() const { return lastUpdatedBy == CATSource; }
|
||||||
|
inline bool updatedByRaduino() const { return lastUpdatedBy == RaduinoSource; }
|
||||||
|
|
||||||
|
inline void clearUpdate() { lastUpdatedBy = NoSource; }
|
||||||
|
inline void setRaduinoUpdate() { lastUpdatedBy = RaduinoSource; }
|
||||||
|
inline void setCATUpdate() { lastUpdatedBy = CATSource; }
|
||||||
|
|
||||||
|
inline void setFreqA(unsigned long freq, bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.vfo[0] = freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setFreqB(unsigned long freq, bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.vfo[1] = freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setRIT(short offset, bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.rit = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setXIT(short offset, bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.xit = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void selectVFOA(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags &= ~UBITX_VFOB_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void selectVFOB(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags |= UBITX_VFOB_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void toggleVFO(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags ^= UBITX_VFOB_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void splitOn(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags |= UBITX_SPLIT_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void splitOff(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags &= ~UBITX_SPLIT_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ritOn(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags |= UBITX_RIT_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ritOff(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags &= ~UBITX_RIT_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void xitOn(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags |= UBITX_XIT_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void xitOff(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags &= ~UBITX_XIT_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void cwOn(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags |= UBITX_CW_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void cwOff(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags &= ~UBITX_CW_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void selectLSB(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags &= ~UBITX_USB_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void selectUSB(bool isCAT = false) {
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
state.flags |= UBITX_USB_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void aiOn() { autoInfo = true; }
|
||||||
|
inline void aiOff() { autoInfo = false; }
|
||||||
|
|
||||||
|
uint8_t* const stateAsBytes() const { return (uint8_t* const)&state; }
|
||||||
|
|
||||||
|
inline void updateState(UBitxRigState& r, bool isCAT = false) {
|
||||||
|
if ((r.vfo[0] == state.vfo[0]) &&
|
||||||
|
(r.vfo[1] == state.vfo[1]) &&
|
||||||
|
(r.rit == state.rit) &&
|
||||||
|
(r.xit == state.xit) &&
|
||||||
|
(r.flags == state.flags)) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
state = r;
|
||||||
|
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool autoInfo = false;
|
||||||
|
UpdateSource lastUpdatedBy = NoSource;
|
||||||
|
UBitxRigState state;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern UBitxRig Rig;
|
||||||
|
|
||||||
|
#endif
|
174
TeensyDSP/RigState.h
Normal file
174
TeensyDSP/RigState.h
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
#ifndef __RigState_h__
|
||||||
|
#define __RigState_h__
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#define UBITX_VFOA_UPDATE 0x00000001
|
||||||
|
#define UBITX_VFOB_UPDATE 0x00000002
|
||||||
|
#define UBITX_RIT_UPDATE 0x00000004
|
||||||
|
#define UBITX_XIT_UPDATE 0x00000008
|
||||||
|
#define UBITX_FLAGS_UPDATE 0x00000010
|
||||||
|
|
||||||
|
#define UBITX_VFOB_FLAG 0x00000001
|
||||||
|
#define UBITX_SPLIT_FLAG 0x00000002
|
||||||
|
#define UBITX_RIT_FLAG 0x00000004
|
||||||
|
#define UBITX_XIT_FLAG 0x00000008
|
||||||
|
#define UBITX_CW_FLAG 0x00000010
|
||||||
|
#define UBITX_USB_FLAG 0x00000020
|
||||||
|
#define UBITX_TX_FLAG 0x00000040
|
||||||
|
|
||||||
|
struct UBitxRigState {
|
||||||
|
uint32_t header = 0;
|
||||||
|
uint32_t vfo[2];
|
||||||
|
int32_t rit;
|
||||||
|
int32_t xit;
|
||||||
|
uint32_t flags = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
template<typename T, int ID>
|
||||||
|
struct Field {
|
||||||
|
byte id = ID;
|
||||||
|
bool dirty;
|
||||||
|
T data;
|
||||||
|
|
||||||
|
inline size_t sizeOfWrite() { return dirty ? sizeof(byte) + sizeof(T) : 0; }
|
||||||
|
|
||||||
|
template<typename STREAM> void writeChanges() {
|
||||||
|
if (dirty) {
|
||||||
|
STREAM().write(id);
|
||||||
|
STREAM().write((byte*)&data, sizeof(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename STREAM> int read() {
|
||||||
|
size_t len = 0;
|
||||||
|
byte* ptr = (byte*)&data;
|
||||||
|
while (STREAM().available() && len < sizeof(T)) {
|
||||||
|
ptr[len++] = STREAM().read();
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void merge(Field<T,ID>& f) {
|
||||||
|
if (dirty) {
|
||||||
|
f.data = data;
|
||||||
|
f.dirty = true;
|
||||||
|
} else if (f.dirty) {
|
||||||
|
data = f.data;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void markClean() { dirty = false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RigState {
|
||||||
|
Field<uint32_t, 0> vfoA;
|
||||||
|
Field<uint32_t, 1> vfoB;
|
||||||
|
Field<int32_t, 2> rit;
|
||||||
|
Field<int32_t, 3> xit;
|
||||||
|
Field<uint32_t, 4> flags;
|
||||||
|
|
||||||
|
inline size_t sizeOfWrite() {
|
||||||
|
size_t size = 0;
|
||||||
|
size += vfoA.sizeOfWrite();
|
||||||
|
size += vfoB.sizeOfWrite();
|
||||||
|
size += rit.sizeOfWrite();
|
||||||
|
size += xit.sizeOfWrite();
|
||||||
|
size += flags.sizeOfWrite();
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename STREAM> void writeChanges() {
|
||||||
|
vfoA.writeChanges<STREAM>();
|
||||||
|
vfoB.writeChanges<STREAM>();
|
||||||
|
rit.writeChanges<STREAM>();
|
||||||
|
xit.writeChanges<STREAM>();
|
||||||
|
flags.writeChanges<STREAM>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename STREAM> void readChanges(size_t size) {
|
||||||
|
size_t len = 0;
|
||||||
|
while (STREAM().available() && len < size) {
|
||||||
|
switch(STREAM().read()) {
|
||||||
|
case 0:
|
||||||
|
len += vfoA.read<STREAM>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
len += vfoB.read<STREAM>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
len += rit.read<STREAM>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
len += xit.read<STREAM>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
len += flags.read<STREAM>();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void merge(RigState& r) {
|
||||||
|
vfoA.merge(r.vfoA);
|
||||||
|
vfoB.merge(r.vfoB);
|
||||||
|
rit.merge(r.rit);
|
||||||
|
xit.merge(r.xit);
|
||||||
|
flags.merge(r.flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void markClean(RigState& r) {
|
||||||
|
vfoA.markClean();
|
||||||
|
vfoB.markClean();
|
||||||
|
rit.markClean();
|
||||||
|
xit.markClean();
|
||||||
|
flags.markClean();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Protocol discussion:
|
||||||
|
- I2C master: Raduino
|
||||||
|
- I2C slave: TeensyDSP
|
||||||
|
|
||||||
|
Raduino state:
|
||||||
|
- Baseline uBITX variables
|
||||||
|
- I2C buffer
|
||||||
|
- On I2C transmit: make updates based on current variables
|
||||||
|
- On I2C receive:
|
||||||
|
- Update based on received I2C responses
|
||||||
|
- Update associated variables
|
||||||
|
|
||||||
|
TeensyDSP state:
|
||||||
|
- CAT buffer
|
||||||
|
- Used to receive command from CAT (when commands arrive via Serial)
|
||||||
|
- Used to transmit state to Raduino (when requested via Wire1)
|
||||||
|
- Raduino buffer
|
||||||
|
- Used to receive state from Raduino (when received via Wire1)
|
||||||
|
- Used to transmit responses to CAT (over Serial)
|
||||||
|
- Questions
|
||||||
|
- How can these be synchronized?
|
||||||
|
- At the tail end of an I2C request handler. Before sending the response to the Raduino via I2C:
|
||||||
|
- Copy updated CAT buffer items to the Raduino buffer.
|
||||||
|
- Copy updated Raduino buffer items to the CAT buffer.
|
||||||
|
- In the case of conflicts, CAT wins.
|
||||||
|
- Transmit the CAT buffer state to the Raduino.
|
||||||
|
- TeensyDSP updates 'outgoing' state based on CAT inputs.
|
||||||
|
- Make change to data.
|
||||||
|
- Mark data as dirty, if different than incoming state.
|
||||||
|
- When requested, Teensy DSP sends 'outgoing' state to Raduino.
|
||||||
|
- Send dirty data over I2C.
|
||||||
|
- Mark data as clean.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
@@ -8,31 +8,39 @@
|
|||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
#ifndef UBITX_SENSORS_S_METER_PIN
|
#ifndef UBITX_SENSORS_S_METER_PIN
|
||||||
#define UBITX_SENSORS_S_METER_PIN 27
|
#define UBITX_SENSORS_S_METER_PIN 28
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef UBITX_SENSORS_FWD_PWR_PIN
|
#ifndef UBITX_SENSORS_FWD_PWR_PIN
|
||||||
#define UBITX_SENSORS_FWD_PWR_PIN 20
|
#define UBITX_SENSORS_FWD_PWR_PIN 26
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef UBITX_SENSORS_REV_PWR_PIN
|
#ifndef UBITX_SENSORS_REV_PWR_PIN
|
||||||
#define UBITX_SENSORS_REV_PWR_PIN 28
|
#define UBITX_SENSORS_REV_PWR_PIN 20
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef UBITX_SENSORS_SUPPLY_PIN
|
#ifndef UBITX_SENSORS_SUPPLY_PIN
|
||||||
#define UBITX_SENSORS_SUPPLY_PIN 21
|
#define UBITX_SENSORS_SUPPLY_PIN 21
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef UBITX_SENSORS_SPARE1_PIN
|
||||||
|
#define UBITX_SENSORS_SPARE1_PIN 27
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef UBITX_SENSORS_SPARE2_PIN
|
||||||
|
#define UBITX_SENSORS_SPARE2_PIN 31
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef UBITX_SENSORS_AVG_SAMPLES
|
#ifndef UBITX_SENSORS_AVG_SAMPLES
|
||||||
#define UBITX_SENSORS_AVG_SAMPLES 16
|
#define UBITX_SENSORS_AVG_SAMPLES 16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef UBITX_SENSORS_S_METER_R1
|
#ifndef UBITX_SENSORS_S_METER_R1
|
||||||
#define UBITX_SENSORS_S_METER_R1 22000.0
|
#define UBITX_SENSORS_S_METER_R1 0.0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef UBITX_SENSORS_S_METER_R2
|
#ifndef UBITX_SENSORS_S_METER_R2
|
||||||
#define UBITX_SENSORS_S_METER_R2 33000.0
|
#define UBITX_SENSORS_S_METER_R2 1.0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef UBITX_SENSORS_FWD_PWR_R1
|
#ifndef UBITX_SENSORS_FWD_PWR_R1
|
||||||
@@ -101,6 +109,8 @@ const int uBitxSensorsSMeterPin = UBITX_SENSORS_S_METER_PIN;
|
|||||||
const int uBitxSensorsFwdPwrPin = UBITX_SENSORS_FWD_PWR_PIN;
|
const int uBitxSensorsFwdPwrPin = UBITX_SENSORS_FWD_PWR_PIN;
|
||||||
const int uBitxSensorsRevPwrPin = UBITX_SENSORS_REV_PWR_PIN;
|
const int uBitxSensorsRevPwrPin = UBITX_SENSORS_REV_PWR_PIN;
|
||||||
const int uBitxSensorsSupplyPin = UBITX_SENSORS_SUPPLY_PIN;
|
const int uBitxSensorsSupplyPin = UBITX_SENSORS_SUPPLY_PIN;
|
||||||
|
const int uBitxSensorsSpare1Pin = UBITX_SENSORS_SPARE1_PIN;
|
||||||
|
const int uBitxSensorsSpare2Pin = UBITX_SENSORS_SPARE2_PIN;
|
||||||
const int uBitxSensorsAvgSamples = UBITX_SENSORS_AVG_SAMPLES;
|
const int uBitxSensorsAvgSamples = UBITX_SENSORS_AVG_SAMPLES;
|
||||||
const float uBitxSensorsSMeterR1 = UBITX_SENSORS_S_METER_R1;
|
const float uBitxSensorsSMeterR1 = UBITX_SENSORS_S_METER_R1;
|
||||||
const float uBitxSensorsSMeterR2 = UBITX_SENSORS_S_METER_R2;
|
const float uBitxSensorsSMeterR2 = UBITX_SENSORS_S_METER_R2;
|
||||||
@@ -162,10 +172,15 @@ class TrailingAverage {
|
|||||||
* The new element/value to incorporate into the average.
|
* The new element/value to incorporate into the average.
|
||||||
*/
|
*/
|
||||||
inline void add(T val) {
|
inline void add(T val) {
|
||||||
int last = (current - 1) % N;
|
//int last = (current - 1) % N;
|
||||||
average -= data[last];
|
//average -= data[last];
|
||||||
current = (current + 1) % N;
|
//current = (current + 1) % N;
|
||||||
average += data[current] / divisor;
|
//data[current] = val / divisor;
|
||||||
|
//average += data[current];
|
||||||
|
average -= data[current];
|
||||||
|
data[current] = val / divisor;
|
||||||
|
average += data[current];
|
||||||
|
current = (current + 1) % N;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -200,12 +215,16 @@ class UBitxSensors {
|
|||||||
sMeterPin(uBitxSensorsSMeterPin),
|
sMeterPin(uBitxSensorsSMeterPin),
|
||||||
fwdPwrPin(uBitxSensorsFwdPwrPin),
|
fwdPwrPin(uBitxSensorsFwdPwrPin),
|
||||||
revPwrPin(uBitxSensorsRevPwrPin),
|
revPwrPin(uBitxSensorsRevPwrPin),
|
||||||
supplyPin(uBitxSensorsSupplyPin)
|
supplyPin(uBitxSensorsSupplyPin),
|
||||||
|
spare1Pin(uBitxSensorsSpare1Pin),
|
||||||
|
spare2Pin(uBitxSensorsSpare2Pin)
|
||||||
{
|
{
|
||||||
pinMode(sMeterPin, INPUT); // analog
|
pinMode(sMeterPin, INPUT); // analog
|
||||||
pinMode(fwdPwrPin, INPUT); // analog
|
pinMode(fwdPwrPin, INPUT); // analog
|
||||||
pinMode(revPwrPin, INPUT); // analog
|
pinMode(revPwrPin, INPUT); // analog
|
||||||
pinMode(supplyPin, INPUT); // analog
|
pinMode(supplyPin, INPUT); // analog
|
||||||
|
pinMode(spare1Pin, INPUT); // analog
|
||||||
|
pinMode(spare2Pin, INPUT); // analog
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -222,8 +241,8 @@ class UBitxSensors {
|
|||||||
* measurements by reading the associated ADC pin.
|
* measurements by reading the associated ADC pin.
|
||||||
*/
|
*/
|
||||||
void updatePower() {
|
void updatePower() {
|
||||||
ADC::Sync_result value = adc.analogSyncRead(fwdPwrPin, revPwrPin);
|
ADC::Sync_result value = adc.analogSyncRead(revPwrPin, fwdPwrPin);
|
||||||
|
|
||||||
float fwdV = HF::adcIn(value.result_adc0);
|
float fwdV = HF::adcIn(value.result_adc0);
|
||||||
float revV = HF::adcIn(value.result_adc1);
|
float revV = HF::adcIn(value.result_adc1);
|
||||||
|
|
||||||
@@ -263,7 +282,7 @@ class UBitxSensors {
|
|||||||
* @return Scaled S-Meter reading.
|
* @return Scaled S-Meter reading.
|
||||||
*/
|
*/
|
||||||
int sMeterScaled() {
|
int sMeterScaled() {
|
||||||
float sig = sMeter.read();
|
int sig = sMeter.read() >> 2;
|
||||||
// small number of elements; just doing a linear search
|
// small number of elements; just doing a linear search
|
||||||
for (int i = uBitxSensorsSMeterLevels; i > 0; i--) {
|
for (int i = uBitxSensorsSMeterLevels; i > 0; i--) {
|
||||||
if (sig > uBitxSensorsSMeterValues[i - 1]) {
|
if (sig > uBitxSensorsSMeterValues[i - 1]) {
|
||||||
@@ -328,6 +347,8 @@ class UBitxSensors {
|
|||||||
int fwdPwrPin;
|
int fwdPwrPin;
|
||||||
int revPwrPin;
|
int revPwrPin;
|
||||||
int supplyPin;
|
int supplyPin;
|
||||||
|
int spare1Pin;
|
||||||
|
int spare2Pin;
|
||||||
|
|
||||||
// Buffers for averages
|
// Buffers for averages
|
||||||
TrailingAverage<int, uBitxSensorsAvgSamples> sMeter;
|
TrailingAverage<int, uBitxSensorsAvgSamples> sMeter;
|
||||||
|
@@ -7,32 +7,42 @@
|
|||||||
|
|
||||||
UBitxTR TR(DSP);
|
UBitxTR TR(DSP);
|
||||||
|
|
||||||
void UBitxTR::update(bool cw) {
|
void UBitxTR::update(bool cw, bool extKey) {
|
||||||
|
updateKey();
|
||||||
|
|
||||||
|
if (cw) {
|
||||||
|
if ((keyEnable && keyDown) || extKey) {
|
||||||
|
setTX();
|
||||||
|
} else {
|
||||||
|
setRX();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
updatePTT();
|
updatePTT();
|
||||||
updateVOX();
|
updateVOX();
|
||||||
updateKey();
|
|
||||||
|
|
||||||
if (isTX) {
|
if (isTX) {
|
||||||
// If we are currently transmitting, then ANY T/R release (key
|
// If we are currently transmitting, then ANY T/R release (key
|
||||||
// release) will result in exitting transmit... except for VOX
|
// release) will result in exitting transmit... except for VOX
|
||||||
// and CAT which can only function as a release if it was enabled.
|
// and CAT which can only function as a release if it was enabled.
|
||||||
if (pttReleased() || keyReleased() ||
|
if (pttReleased() || keyReleased() ||
|
||||||
(voxEnabled && voxDeactivated()) ||
|
(voxEnable && voxDeactivated()) ||
|
||||||
(catEnabled && catDeactivated())) {
|
(catEnable && catDeactivated())) {
|
||||||
// first, stop transmitting; then, setup RX audio
|
// first, stop transmitting; then, setup RX audio
|
||||||
DBGCMD( setRX() );
|
DBGCMD( setRX() );
|
||||||
DBGCMD( dsp.rx() );
|
DBGCMD( dsp.rx() );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((pttEnabled && pttPressed()) || (voxEnabled && voxActivated())) {
|
if ((pttEnable && pttPressed()) || (voxEnable && voxActivated())) {
|
||||||
// first, setup TX audio; then, start transmitting (from Mic)
|
// first, setup TX audio; then, start transmitting (from Mic)
|
||||||
DBGCMD( dsp.txMicIn() );
|
DBGCMD( dsp.txMicIn() );
|
||||||
DBGCMD( setTX() );
|
DBGCMD( setTX() );
|
||||||
} else if (keyEnabled && keyPressed()) {
|
} else if (keyEnable && keyPressed()) {
|
||||||
// first, setup TX audio; then, start transmitting (from Line In)
|
// first, setup TX audio; then, start transmitting (from Line In)
|
||||||
DBGCMD( dsp.txLineIn() );
|
DBGCMD( dsp.txLineIn() );
|
||||||
DBGCMD( setTX() );
|
DBGCMD( setTX() );
|
||||||
} else if (catEnabled && catActivated()) {
|
} else if (catEnable && catActivated()) {
|
||||||
// first, setup TX audio; then, start transmitting (USB)
|
// first, setup TX audio; then, start transmitting (USB)
|
||||||
DBGCMD( dsp.txUSBIn() );
|
DBGCMD( dsp.txUSBIn() );
|
||||||
DBGCMD( setTX() );
|
DBGCMD( setTX() );
|
||||||
|
@@ -36,18 +36,33 @@ class UBitxTR {
|
|||||||
DBGCMD( disableVOX() );
|
DBGCMD( disableVOX() );
|
||||||
DBGCMD( enableKey() );
|
DBGCMD( enableKey() );
|
||||||
DBGCMD( enableCAT() );
|
DBGCMD( enableCAT() );
|
||||||
|
|
||||||
|
DBGCMD( setRX() );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void enablePTT() { pttEnabled = true; }
|
inline void enablePTT() { pttEnable = true; }
|
||||||
inline void enableVOX() { voxEnabled = true; }
|
inline void enableVOX() { voxEnable = true; }
|
||||||
inline void enableKey() { keyEnabled = true; }
|
inline void enableKey() { keyEnable = true; }
|
||||||
inline void enableCAT() { catEnabled = true; }
|
inline void enableCAT() { catEnable = true; }
|
||||||
inline void disablePTT() { pttEnabled = false; }
|
inline void disablePTT() { pttEnable = false; }
|
||||||
inline void disableVOX() { voxEnabled = false; }
|
inline void disableVOX() { voxEnable = false; }
|
||||||
inline void disableKey() { keyEnabled = false; }
|
inline void disableKey() { keyEnable = false; }
|
||||||
inline void disableCAT() { catEnabled = false; }
|
inline void disableCAT() { catEnable = false; }
|
||||||
|
|
||||||
|
|
||||||
|
inline bool pttEnabled() { return pttEnable; }
|
||||||
|
inline bool voxEnabled() { return voxEnable; }
|
||||||
|
inline bool keyEnabled() { return keyEnable; }
|
||||||
|
inline bool catEnabled() { return catEnable; }
|
||||||
|
|
||||||
|
inline bool pttPressed() { return ptt.fell(); }
|
||||||
|
inline bool pttReleased() { return ptt.rose(); }
|
||||||
|
inline bool voxActivated() { return (L_voxActive != voxActive) && L_voxActive; }
|
||||||
|
inline bool voxDeactivated() { return (L_voxActive != voxActive) && voxActive; }
|
||||||
|
inline bool keyPressed() { return (L_keyDown != keyDown) && L_keyDown; }
|
||||||
|
inline bool keyReleased() { return (L_keyDown != keyDown) && keyDown; }
|
||||||
|
inline bool catActivated() { return (L_catActive != catActive) && L_catActive; }
|
||||||
|
inline bool catDeactivated() { return (L_catActive != catActive) && catActive; }
|
||||||
|
|
||||||
inline void catTX() {
|
inline void catTX() {
|
||||||
L_catActive = catActive;
|
L_catActive = catActive;
|
||||||
catActive = true;
|
catActive = true;
|
||||||
@@ -72,8 +87,12 @@ class UBitxTR {
|
|||||||
* @param cw
|
* @param cw
|
||||||
* True if CW mode is currently active; false otherwise.
|
* True if CW mode is currently active; false otherwise.
|
||||||
* Different/faster logic is used in CW mode.
|
* Different/faster logic is used in CW mode.
|
||||||
|
*
|
||||||
|
* @param extKey
|
||||||
|
* True if an external keying signal (ie. CW keyer) is
|
||||||
|
* currently active (ie. key down).
|
||||||
*/
|
*/
|
||||||
void update(bool cw = false);
|
void update(bool cw = false, bool extKey = false);
|
||||||
|
|
||||||
void end() {
|
void end() {
|
||||||
}
|
}
|
||||||
@@ -94,48 +113,16 @@ class UBitxTR {
|
|||||||
ptt.update();
|
ptt.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool pttPressed() {
|
|
||||||
return ptt.fell();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool pttReleased() {
|
|
||||||
return ptt.rose();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void updateVOX() {
|
inline void updateVOX() {
|
||||||
L_voxActive = voxActive;
|
L_voxActive = voxActive;
|
||||||
voxActive = (digitalRead(voxPin) == LOW);
|
voxActive = (digitalRead(voxPin) == LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool voxActivated() {
|
|
||||||
return (L_voxActive != voxActive) && L_voxActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool voxDeactivated() {
|
|
||||||
return (L_voxActive != voxActive) && voxActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void updateKey() {
|
inline void updateKey() {
|
||||||
L_keyDown = keyDown;
|
L_keyDown = keyDown;
|
||||||
keyDown = (digitalRead(keyPin) == LOW);
|
keyDown = (digitalRead(keyPin) == LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool keyPressed() {
|
|
||||||
return (L_keyDown != keyDown) && L_keyDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool keyReleased() {
|
|
||||||
return (L_keyDown != keyDown) && keyDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool catActivated() {
|
|
||||||
return (L_catActive != catActive) && L_catActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool catDeactivated() {
|
|
||||||
return (L_catActive != catActive) && catActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
UBitxDSP& dsp;
|
UBitxDSP& dsp;
|
||||||
|
|
||||||
Bounce ptt;
|
Bounce ptt;
|
||||||
@@ -147,10 +134,10 @@ class UBitxTR {
|
|||||||
|
|
||||||
bool isTX = false;
|
bool isTX = false;
|
||||||
|
|
||||||
bool pttEnabled = false;
|
bool pttEnable = false;
|
||||||
bool voxEnabled = false;
|
bool voxEnable = false;
|
||||||
bool keyEnabled = false;
|
bool keyEnable = false;
|
||||||
bool catEnabled = false;
|
bool catEnable = false;
|
||||||
|
|
||||||
bool voxActive = false;
|
bool voxActive = false;
|
||||||
bool L_voxActive = false;
|
bool L_voxActive = false;
|
||||||
|
358
TeensyDSP/TS590.cpp
Normal file
358
TeensyDSP/TS590.cpp
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include "TS590.h"
|
||||||
|
#include "Debug.h"
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Send a command to the PC via CAT. Note that the command
|
||||||
|
* should not include the trailing terminator (;). That will
|
||||||
|
* be automatically added.
|
||||||
|
* @param format
|
||||||
|
* A printf-style format string.
|
||||||
|
* @param args
|
||||||
|
* Zero or more arguments to include in the command.
|
||||||
|
*/
|
||||||
|
void ts590SendCommand(const char* format, ...) {
|
||||||
|
static char outBuf[ts590CommandMaxLength];
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vsprintf(outBuf, format, args);
|
||||||
|
va_end(args);
|
||||||
|
Serial.print(outBuf);
|
||||||
|
Serial.print(";");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Create a new CAT command. It should be initialized with
|
||||||
|
* a 2-character command prefix.
|
||||||
|
* @param pre
|
||||||
|
* A 2-character command prefix. If more than 2 characters
|
||||||
|
* are supplied, only the first two will be used. If less
|
||||||
|
* than two are supplied, then the command will be
|
||||||
|
* initialized with a null prefix.
|
||||||
|
*/
|
||||||
|
TS590Command::TS590Command(const char* pre) {
|
||||||
|
if (strlen(pre) >= 2) {
|
||||||
|
myPrefix[0] = pre[0];
|
||||||
|
myPrefix[1] = pre[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TS590Command::~TS590Command() {}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Determine whether this is a Read command or not. by
|
||||||
|
* default, if it's a 2-letter command, it's a Read.
|
||||||
|
* @return True if a Read command; false otherwise.
|
||||||
|
*/
|
||||||
|
bool TS590Command::isReadCommand(const char* cmd) const {
|
||||||
|
if (strlen(cmd) == 2) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Process the provided command. If the command is a Set
|
||||||
|
* command, it calls handleCommand(). If Auto Information
|
||||||
|
* is eet (by the rig), sendResponse() is called at the end.
|
||||||
|
* If the command is a Read command, it also calls
|
||||||
|
* sendResponse(). Finally, if necessary, it will return
|
||||||
|
* any error codes to the PC.
|
||||||
|
* @param cmd
|
||||||
|
* The current command string received from the PC via CAT.
|
||||||
|
* It should be null-terminated, and should no longer have
|
||||||
|
* the terminator (;).
|
||||||
|
*/
|
||||||
|
void TS590Command::process(const char* cmd) {
|
||||||
|
theError = NoError;
|
||||||
|
|
||||||
|
if (isReadCommand(cmd)) {
|
||||||
|
DBGCMD( sendResponse(cmd) );
|
||||||
|
} else {
|
||||||
|
DBGCMD( handleCommand(cmd) );
|
||||||
|
switch(theError) {
|
||||||
|
case NoError:
|
||||||
|
if (theRig->getAI()) {
|
||||||
|
DBGCMD( sendResponse(cmd) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SyntaxError:
|
||||||
|
DBGCMD( ts590SyntaxError() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CommError:
|
||||||
|
DBGCMD( ts590CommError() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ProcessError:
|
||||||
|
DBGCMD( ts590ProcessError() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Set the syntax error flag. This is cleared at the
|
||||||
|
* beginning of each call to process().
|
||||||
|
*/
|
||||||
|
void TS590Command::setSyntaxError() {
|
||||||
|
theError = SyntaxError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Set the comms error flag. This is cleared at the
|
||||||
|
* beginning of each call to process().
|
||||||
|
*/
|
||||||
|
void TS590Command::setCommError() {
|
||||||
|
theError = CommError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Set the process error flag. This is cleared at the
|
||||||
|
* beginning of each call to process().
|
||||||
|
*/
|
||||||
|
void TS590Command::setProcessError() {
|
||||||
|
theError = ProcessError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Set the rig that will be used to process commands.
|
||||||
|
* @param r
|
||||||
|
* Pointer to the UBitxRig object.
|
||||||
|
*/
|
||||||
|
void TS590Command::setRig(UBitxRig* r) {
|
||||||
|
theRig = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
UBitxRig* TS590Command::theRig = &Rig;
|
||||||
|
TS590Error TS590Command::theError = NoError;
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
void TS590_FR::handleCommand(const char* cmd) {
|
||||||
|
if (strlen(cmd) == 3) {
|
||||||
|
switch (cmd[2]) {
|
||||||
|
case '0':
|
||||||
|
rig()->selectVFOA(true);
|
||||||
|
rig()->splitOff(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '1':
|
||||||
|
rig()->selectVFOB(true);
|
||||||
|
rig()->splitOff(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '2':
|
||||||
|
// TODO: Need to add something for channel mode.
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
setSyntaxError();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setSyntaxError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TS590_FR::sendResponse(const char* cmd) {
|
||||||
|
if (rig()->isVFOA()) {
|
||||||
|
ts590SendCommand("FR0");
|
||||||
|
} else if (rig()->isVFOB()) {
|
||||||
|
ts590SendCommand("FR1");
|
||||||
|
} else {
|
||||||
|
ts590SendCommand("FR2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
void TS590_FT::handleCommand(const char* cmd) {
|
||||||
|
if (strlen(cmd) == 3) {
|
||||||
|
switch (cmd[2]) {
|
||||||
|
case '0':
|
||||||
|
if (rig()->isVFOA()) {
|
||||||
|
rig()->splitOff(true);
|
||||||
|
} else if (rig()->isVFOB()) {
|
||||||
|
rig()->splitOn(true);
|
||||||
|
} else {
|
||||||
|
setSyntaxError();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '1':
|
||||||
|
if (rig()->isVFOA()) {
|
||||||
|
rig()->splitOn(true);
|
||||||
|
} else if (rig()->isVFOB()) {
|
||||||
|
rig()->splitOff(true);
|
||||||
|
} else {
|
||||||
|
setSyntaxError();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
setSyntaxError();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setSyntaxError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TS590_FT::sendResponse(const char* cmd) {
|
||||||
|
if (rig()->isVFOA()) {
|
||||||
|
ts590SendCommand(rig()->isSplit() ? "FT1" : "FT0");
|
||||||
|
} else if (rig()->isVFOB()) {
|
||||||
|
ts590SendCommand(rig()->isSplit() ? "FT0" : "FT1");
|
||||||
|
} else {
|
||||||
|
ts590SendCommand("FT2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
void TS590_MD::handleCommand(const char* cmd) {
|
||||||
|
if (strlen(cmd) == 3) {
|
||||||
|
switch (cmd[2]) {
|
||||||
|
case '0': // None (setting failure)
|
||||||
|
case '4': // FM - not supported
|
||||||
|
case '5': // AM - not supported
|
||||||
|
case '6': // FSK - not supported
|
||||||
|
case '8': // None (setting failure)
|
||||||
|
case '9': // FSK-R - not supported
|
||||||
|
setProcessError();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '1': // LSB
|
||||||
|
rig()->selectLSB(true);
|
||||||
|
rig()->cwOff(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '2': // USB
|
||||||
|
rig()->selectUSB(true);
|
||||||
|
rig()->cwOff(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '3': // CW
|
||||||
|
rig()->selectUSB(true);
|
||||||
|
rig()->cwOn(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '7': // CW-R
|
||||||
|
rig()->selectLSB(true);
|
||||||
|
rig()->cwOn(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
setSyntaxError();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setSyntaxError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TS590_MD::sendResponse(const char* cmd) {
|
||||||
|
if (rig()->isCW()) {
|
||||||
|
if (rig()->isUSB()) {
|
||||||
|
ts590SendCommand("MD3");
|
||||||
|
} else {
|
||||||
|
ts590SendCommand("MD7");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rig()->isUSB()) {
|
||||||
|
ts590SendCommand("MD2");
|
||||||
|
} else {
|
||||||
|
ts590SendCommand("MD1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
TS590_FA cmdFA;
|
||||||
|
TS590_FB cmdFB;
|
||||||
|
TS590_FR cmdFR;
|
||||||
|
TS590_FT cmdFT;
|
||||||
|
TS590_MD cmdMD;
|
||||||
|
|
||||||
|
TS590Command* catCommands[] = {
|
||||||
|
&cmdFA,
|
||||||
|
&cmdFB,
|
||||||
|
&cmdFR,
|
||||||
|
&cmdFT,
|
||||||
|
&cmdMD
|
||||||
|
};
|
||||||
|
int numCatCommands = sizeof(catCommands) / sizeof(catCommands[0]);
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
void UBitxTS590::begin() {
|
||||||
|
Serial.begin(9600); // USB is always 12 Mbit/sec
|
||||||
|
#ifdef DEBUG
|
||||||
|
delay(500);
|
||||||
|
Serial.print("DBG: Number of CAT commands: ");
|
||||||
|
Serial.println(numCommands);
|
||||||
|
for (int i = 0; i < numCommands; i++) {
|
||||||
|
Serial.print(" ");
|
||||||
|
Serial.println(commands[i]->prefix());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void UBitxTS590::update() {
|
||||||
|
char incomingChar;
|
||||||
|
|
||||||
|
while (Serial.available()) {
|
||||||
|
if (bufLen < ts590CommandMaxLength) {
|
||||||
|
incomingChar = Serial.read();
|
||||||
|
if (incomingChar == ';') {
|
||||||
|
buf[bufLen++] = '\0';
|
||||||
|
strupr(buf);
|
||||||
|
processCommand();
|
||||||
|
} else if (incomingChar == '\n' && bufLen == 0) {
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
buf[bufLen++] = incomingChar;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// too long... we're going to bail on this.
|
||||||
|
ts590SyntaxError();
|
||||||
|
bufLen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef class TS590Command* PCmd;
|
||||||
|
|
||||||
|
int compareCATCommands(const void* a, const void* b) {
|
||||||
|
TS590Command const *B = *(TS590Command const **)b;
|
||||||
|
int cmp = strncmp((char*)a, (char*)B->prefix(), 2);
|
||||||
|
#ifdef DEBUG
|
||||||
|
Serial.print("Comparison: ");
|
||||||
|
Serial.print((char*)a);
|
||||||
|
Serial.print(" ? ");
|
||||||
|
Serial.print((char*)B->prefix());
|
||||||
|
Serial.print(" --> ");
|
||||||
|
Serial.println(cmp);
|
||||||
|
#endif
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UBitxTS590::processCommand() {
|
||||||
|
TS590Command** cmd = (TS590Command**)bsearch(buf, commands, numCommands, sizeof(TS590Command*), compareCATCommands);
|
||||||
|
if (cmd == NULL) {
|
||||||
|
ts590SyntaxError();
|
||||||
|
} else {
|
||||||
|
(*cmd)->process(buf);
|
||||||
|
}
|
||||||
|
bufLen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UBitxTS590 TS590(catCommands, numCatCommands);
|
||||||
|
|
||||||
|
/**********************************************************************/
|
183
TeensyDSP/TS590.h
Normal file
183
TeensyDSP/TS590.h
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
#ifndef __TS590_h__
|
||||||
|
#define __TS590_h__
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "Rig.h"
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
#define TS590_COMMAND_MAX_LENGTH 50 // including terminator (which will get converted to null)
|
||||||
|
|
||||||
|
const int ts590CommandMaxLength = TS590_COMMAND_MAX_LENGTH;
|
||||||
|
|
||||||
|
void ts590SendCommand(const char*, ...);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Send a syntax error response to the PC via CAT.
|
||||||
|
*/
|
||||||
|
inline void ts590SyntaxError() { ts590SendCommand("?"); }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Send a communications error response to the PC via CAT.
|
||||||
|
*/
|
||||||
|
inline void ts590CommError() { ts590SendCommand("E"); }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Send a processing error response to the PC via CAT.
|
||||||
|
*/
|
||||||
|
inline void ts590ProcessError() { ts590SendCommand("O"); }
|
||||||
|
|
||||||
|
enum TS590Error {
|
||||||
|
NoError,
|
||||||
|
SyntaxError,
|
||||||
|
CommError,
|
||||||
|
ProcessError
|
||||||
|
};
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief A TS590S/SG "CAT" command. This is the base class for all
|
||||||
|
* CAT commands.
|
||||||
|
*/
|
||||||
|
class TS590Command {
|
||||||
|
public:
|
||||||
|
TS590Command(const char* pre);
|
||||||
|
virtual ~TS590Command() = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Return the 2-character prefix for the command.
|
||||||
|
* @return The 2-character prefix for the command.
|
||||||
|
*/
|
||||||
|
inline const char* prefix() const { return &myPrefix[0]; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Return the rig that this command will be used to control.
|
||||||
|
*/
|
||||||
|
inline UBitxRig* rig() const { return theRig; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Handle the provided Set command. If the Set command
|
||||||
|
* results in an error, then set the appropriate flag with
|
||||||
|
* setSyntaxError(), setCommError(), or setProcessError().
|
||||||
|
* @param cmd
|
||||||
|
* The current command string received from the PC via CAT.
|
||||||
|
* It should be null-terminated, and should no longer have
|
||||||
|
* the terminator (;).
|
||||||
|
*/
|
||||||
|
virtual void handleCommand(const char* cmd) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Send a response back to the PC. This assumes a
|
||||||
|
* successful command (no errors).
|
||||||
|
*/
|
||||||
|
virtual void sendResponse(const char* cmd) = 0;
|
||||||
|
|
||||||
|
virtual bool isReadCommand(const char* cmd) const;
|
||||||
|
|
||||||
|
void process(const char* cmd);
|
||||||
|
|
||||||
|
static void setSyntaxError();
|
||||||
|
static void setCommError();
|
||||||
|
static void setProcessError();
|
||||||
|
static void setRig(UBitxRig* r);
|
||||||
|
|
||||||
|
private:
|
||||||
|
char myPrefix[3] = "\0\0";
|
||||||
|
static TS590Error theError;
|
||||||
|
static UBitxRig* theRig;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief CAT command for setting or reading the VFO A/B frequency.
|
||||||
|
*/
|
||||||
|
template<bool VFOA>
|
||||||
|
class TS590_FAB : public TS590Command {
|
||||||
|
public:
|
||||||
|
TS590_FAB(): TS590Command(VFOA ? "FA" : "FB") {}
|
||||||
|
|
||||||
|
virtual void handleCommand(const char* cmd) {
|
||||||
|
if (strlen(cmd) == 13) {
|
||||||
|
unsigned long freq = strtoul(&cmd[2], NULL, 10);
|
||||||
|
if (VFOA) {
|
||||||
|
rig()->setFreqA(freq, true);
|
||||||
|
} else {
|
||||||
|
rig()->setFreqB(freq, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setSyntaxError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void sendResponse(const char* cmd) {
|
||||||
|
ts590SendCommand(VFOA ? "FA%011u" : "FB%011u", VFOA ? rig()->getFreqA() : rig()->getFreqB());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef TS590_FAB<true> TS590_FA;
|
||||||
|
typedef TS590_FAB<false> TS590_FB;
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief CAT command for setting the receiver VFO. This will always
|
||||||
|
* disable split mode, if it was previously enabled.
|
||||||
|
*/
|
||||||
|
class TS590_FR : public TS590Command {
|
||||||
|
public:
|
||||||
|
TS590_FR(): TS590Command("FR") {}
|
||||||
|
virtual void handleCommand(const char* cmd);
|
||||||
|
virtual void sendResponse(const char* cmd);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief CAT command for setting the transmitter VFO. If it is
|
||||||
|
* different than the receiver VFO, then split mode will be
|
||||||
|
* automatically enabled.
|
||||||
|
*/
|
||||||
|
class TS590_FT : public TS590Command {
|
||||||
|
public:
|
||||||
|
TS590_FT(): TS590Command("FT") {}
|
||||||
|
virtual void handleCommand(const char* cmd);
|
||||||
|
virtual void sendResponse(const char* cmd);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief CAT command for setting the mode.
|
||||||
|
*/
|
||||||
|
class TS590_MD : public TS590Command {
|
||||||
|
public:
|
||||||
|
TS590_MD(): TS590Command("MD") {}
|
||||||
|
virtual void handleCommand(const char* cmd);
|
||||||
|
virtual void sendResponse(const char* cmd);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
class UBitxTS590 {
|
||||||
|
public:
|
||||||
|
UBitxTS590(TS590Command** cmds, int len): commands(cmds), numCommands(len) {}
|
||||||
|
|
||||||
|
void begin();
|
||||||
|
void update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void processCommand();
|
||||||
|
|
||||||
|
char buf[ts590CommandMaxLength] = {0};
|
||||||
|
int bufLen = 0;
|
||||||
|
TS590Command** commands;
|
||||||
|
int numCommands;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern UBitxTS590 TS590;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**********************************************************************/
|
@@ -10,9 +10,13 @@ KD8CEC, Ian Lee
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "DSP.h"
|
#include "DSP.h"
|
||||||
|
#include "Keyer.h"
|
||||||
#include "Nextion.h"
|
#include "Nextion.h"
|
||||||
|
#include "Rig.h"
|
||||||
|
#include "RigState.h"
|
||||||
#include "Sensors.h"
|
#include "Sensors.h"
|
||||||
#include "TR.h"
|
#include "TR.h"
|
||||||
|
#include "TS590.h"
|
||||||
|
|
||||||
//================================================================
|
//================================================================
|
||||||
//COMMUNICATION SECTION
|
//COMMUNICATION SECTION
|
||||||
@@ -63,3 +67,9 @@ extern int magnitudelimit_low;
|
|||||||
//SWR
|
//SWR
|
||||||
#define I2CMETER_CALCR 0x55 //Calculated SWR Meter
|
#define I2CMETER_CALCR 0x55 //Calculated SWR Meter
|
||||||
#define I2CMETER_UNCALCR 0x54 //Uncalculated SWR Meter
|
#define I2CMETER_UNCALCR 0x54 //Uncalculated SWR Meter
|
||||||
|
|
||||||
|
// Raduino provides updated data to TeensyDSP
|
||||||
|
#define I2CMETER_RIGINF 0x50
|
||||||
|
|
||||||
|
// Raduino requests any CAT updates from TeensyDSP
|
||||||
|
#define I2CMETER_REQCAT 0x51
|
||||||
|
@@ -16,6 +16,11 @@
|
|||||||
//const uint8_t responseFooter[4]={'"', 0xFF, 0xFF, 0xFF};
|
//const uint8_t responseFooter[4]={'"', 0xFF, 0xFF, 0xFF};
|
||||||
//const char hexCodes[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', };
|
//const char hexCodes[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', };
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
int i2cCmdCounter[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
int i2cRespCounter[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned long SAMPLE_INTERVAL = 0;
|
unsigned long SAMPLE_INTERVAL = 0;
|
||||||
|
|
||||||
int i2cCommand = 0;
|
int i2cCommand = 0;
|
||||||
@@ -308,6 +313,12 @@ void sendMeterData(uint8_t isSend)
|
|||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
|
// Startup each of the subsystems, beginning with CAT.
|
||||||
|
DBGCMD( TS590.begin() );
|
||||||
|
DBGCMD( TR.begin() );
|
||||||
|
DBGCMD( Rig.begin() );
|
||||||
|
DBGCMD( DSP.begin() );
|
||||||
|
|
||||||
// load configuration
|
// load configuration
|
||||||
EEPROM.get(EEPROM_DSPTYPE, DSPType);
|
EEPROM.get(EEPROM_DSPTYPE, DSPType);
|
||||||
if (DSPType > 5)
|
if (DSPType > 5)
|
||||||
@@ -350,11 +361,10 @@ void setup()
|
|||||||
SAMPLE_INTERVAL = round(1000000 * (1.0 / SAMPLE_FREQUENCY));
|
SAMPLE_INTERVAL = round(1000000 * (1.0 / SAMPLE_FREQUENCY));
|
||||||
//calculateCoeff(cwDecodeHz); //Set 750Hz //9 * 50 + 300 = 750Hz
|
//calculateCoeff(cwDecodeHz); //Set 750Hz //9 * 50 + 300 = 750Hz
|
||||||
//Serial1.println("Start...");
|
//Serial1.println("Start...");
|
||||||
|
|
||||||
DBGCMD( DSP.begin() );
|
|
||||||
DBGCMD( TR.begin() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sentRigInfFlag = false;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief Receive a command via I2C. The most recent command will be received, which will
|
@brief Receive a command via I2C. The most recent command will be received, which will
|
||||||
indicate which data the DSP should be preparing to return.
|
indicate which data the DSP should be preparing to return.
|
||||||
@@ -362,18 +372,39 @@ void setup()
|
|||||||
Number of bytes received--not used in this procedure.
|
Number of bytes received--not used in this procedure.
|
||||||
*/
|
*/
|
||||||
void i2cReceiveEvent(size_t numBytes)
|
void i2cReceiveEvent(size_t numBytes)
|
||||||
{
|
{
|
||||||
int readCommand = 0;
|
int readCommand = 0;
|
||||||
|
bool exitLoop = false;
|
||||||
|
UBitxRigState tmpState;
|
||||||
|
|
||||||
while (Wire1.available() > 0) // for Last command
|
while (Wire1.available() > 0 && !exitLoop) {
|
||||||
{
|
|
||||||
readCommand = Wire1.read();
|
readCommand = Wire1.read();
|
||||||
// KC4UPR: Note that this looks to be only reading the last command, i.e.
|
if (readCommand == I2CMETER_RIGINF) {
|
||||||
// if multiple commands have been queued up, only the last will get executed.
|
size_t len = 0;
|
||||||
|
uint8_t* const ptr = (uint8_t* const)&tmpState;
|
||||||
|
while ((Wire1.available() > 0) && (len < sizeof(UBitxRigState))) {
|
||||||
|
ptr[len++] = Wire1.read();
|
||||||
|
}
|
||||||
|
if (!Rig.updatedByCAT()) {
|
||||||
|
Rig.updateState(tmpState);
|
||||||
|
}
|
||||||
|
sentRigInfFlag = false; // so we know that we need to send the flag first
|
||||||
|
exitLoop = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// while (Wire1.available() > 0) // for Last command
|
||||||
|
// {
|
||||||
|
// readCommand = Wire1.read();
|
||||||
|
// // KC4UPR: Note that this looks to be only reading the last command, i.e.
|
||||||
|
// // if multiple commands have been queued up, only the last will get executed.
|
||||||
|
// }
|
||||||
|
|
||||||
if (0x50 <= readCommand && readCommand <= 0x59)
|
if (0x50 <= readCommand && readCommand <= 0x59)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
i2cCmdCounter[readCommand - 0x50]++;
|
||||||
|
#endif
|
||||||
i2cCommand = readCommand;
|
i2cCommand = readCommand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,23 +424,62 @@ void i2cRequestEvent(void)
|
|||||||
case I2CMETER_CALCS:
|
case I2CMETER_CALCS:
|
||||||
// Returns an already-calculated S-meter value.
|
// Returns an already-calculated S-meter value.
|
||||||
Wire1.write(scaledSMeter);
|
Wire1.write(scaledSMeter);
|
||||||
|
#ifdef DEBUG
|
||||||
|
i2cRespCounter[i2cCommand - 0x50]++;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case I2CMETER_UNCALCS:
|
case I2CMETER_UNCALCS:
|
||||||
// Returns a raw signal strength value.
|
// Returns a raw signal strength value.
|
||||||
Wire1.write(Sensors.sMeterUnscaled() >> 2); // divided by 4... do we want this?
|
Wire1.write(Sensors.sMeterUnscaled() >> 2); // divided by 4... do we want this?
|
||||||
|
#ifdef DEBUG
|
||||||
|
i2cRespCounter[i2cCommand - 0x50]++;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case I2CMETER_CALCP:
|
case I2CMETER_CALCP:
|
||||||
// Returns a raw forward power value.
|
// Returns a raw forward power value.
|
||||||
Wire1.write(fwdPower);
|
Wire1.write(int(fwdPower * 100.0));
|
||||||
|
#ifdef DEBUG
|
||||||
|
i2cRespCounter[i2cCommand - 0x50]++;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case I2CMETER_CALCR:
|
case I2CMETER_CALCR:
|
||||||
// Returns a raw reverse power value.
|
// Returns a raw reverse power value.
|
||||||
Wire1.write(revPower);
|
Wire1.write(int(revPower * 100.0));
|
||||||
|
#ifdef DEBUG
|
||||||
|
i2cRespCounter[i2cCommand - 0x50]++;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case I2CMETER_RIGINF:
|
||||||
|
// Receive current rig state; transmit any CAT updates, if required.
|
||||||
|
//Wire1.write(catState.header); // temporary - just writing a single, null byte
|
||||||
|
//break;
|
||||||
|
|
||||||
|
case I2CMETER_REQCAT:
|
||||||
|
// Provide latest CAT updates, if any.
|
||||||
|
//Wire1.write(catState.header); // temporary - just writing a single, null byte
|
||||||
|
if (Rig.updatedByCAT()) {
|
||||||
|
if (sentRigInfFlag) {
|
||||||
|
DBGPRINTLN("I2CMETER_REQCAT -- updated by CAT");
|
||||||
|
Wire1.write(Rig.stateAsBytes(), sizeof(UBitxRigState));
|
||||||
|
Rig.clearUpdate();
|
||||||
|
} else {
|
||||||
|
Wire1.write(1);
|
||||||
|
sentRigInfFlag = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DBGPRINTLN("I2CMETER_REQCAT -- NOT updated by CAT");
|
||||||
|
//Wire1.write(Rig.stateAsBytes(), sizeof(uint8_t));
|
||||||
|
Wire1.write(0);
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
i2cRespCounter[i2cCommand - 0x50]++;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -449,16 +519,18 @@ const int adcIntervalMillis = ADC_INTERVAL_MS;
|
|||||||
int frameCounter = 0;
|
int frameCounter = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
//char isProcess = 0; // 0: init, 1: complete ADC sampling, 2: complete FFT
|
//char isProcess = 0; // 0: init, 1: complete ADC sampling, 2: complete FFT
|
||||||
//isProcess = 0;
|
//isProcess = 0;
|
||||||
|
|
||||||
forwardData();
|
// One-shot delay to ensure everything is booted up (primarily, the
|
||||||
|
// Nextion, and secondarily the Raduino.
|
||||||
if (isBooted < 100)
|
if (isBooted < 100)
|
||||||
{
|
{
|
||||||
//Delay 20msec
|
// delay 20msec
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
forwardData();
|
forwardData();
|
||||||
@@ -468,15 +540,35 @@ void loop()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If CW mode, we need to update keying a lot...
|
||||||
|
if (Rig.isCW()) {
|
||||||
|
if (Rig.isCW()) Keyer.doPaddles();
|
||||||
|
TR.update(Rig.isCW(), Keyer.isDown());
|
||||||
|
//if (TR.transmitting()) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start out by forwarding any data sitting in the RX buffer. We will
|
||||||
|
// do this as often as possible.
|
||||||
|
forwardData();
|
||||||
|
|
||||||
if (sinceFrameMillis > frameIntervalMillis) {
|
if (sinceFrameMillis > frameIntervalMillis) {
|
||||||
// Do stuff that we do once per frame--I/O.
|
// Do stuff that we do once per frame--I/O.
|
||||||
// TODO: debug output (frame skipping / utilization).
|
// TODO: debug output (frame skipping / utilization).
|
||||||
sinceFrameMillis = 0;
|
sinceFrameMillis = 0;
|
||||||
|
|
||||||
|
// Update each of the subsystems, beginning with CAT control.
|
||||||
|
TS590.update();
|
||||||
|
TR.update(Rig.isCW(), Keyer.isDown());
|
||||||
|
Rig.update();
|
||||||
|
DSP.update();
|
||||||
|
|
||||||
|
//if (Rig.isCW()) return;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// For debugging, output some debug info every 1.0" (40 frames @ 40 Hz).
|
// For debugging, output some debug info every 1.0" (40 frames @ 40 Hz).
|
||||||
frameCounter++;
|
frameCounter++;
|
||||||
if (frameCounter % 40 == 0) {
|
if (frameCounter % 40 == 0) {
|
||||||
|
Serial.println("======================================================================");
|
||||||
Serial.print("DBG: Frame: ");
|
Serial.print("DBG: Frame: ");
|
||||||
Serial.print(frameCounter);
|
Serial.print(frameCounter);
|
||||||
if (isTX) {
|
if (isTX) {
|
||||||
@@ -489,6 +581,14 @@ void loop()
|
|||||||
} else {
|
} else {
|
||||||
Serial.println(", TR State: RX");
|
Serial.println(", TR State: RX");
|
||||||
}
|
}
|
||||||
|
Serial.print("VFO A: ");
|
||||||
|
Serial.print(Rig.getFreqA());
|
||||||
|
Serial.print(", VFO B: ");
|
||||||
|
Serial.print(Rig.getFreqB());
|
||||||
|
Serial.print(", Data Size: ");
|
||||||
|
Serial.print(sizeof(UBitxRigState));
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("----------------------------------------------------------------------");
|
||||||
Serial.print("DBG: S-Meter Raw: ");
|
Serial.print("DBG: S-Meter Raw: ");
|
||||||
Serial.print(Sensors.sMeterUnscaled());
|
Serial.print(Sensors.sMeterUnscaled());
|
||||||
Serial.print(", S-Meter Scaled: ");
|
Serial.print(", S-Meter Scaled: ");
|
||||||
@@ -501,11 +601,30 @@ void loop()
|
|||||||
Serial.print(fwdPower, 2);
|
Serial.print(fwdPower, 2);
|
||||||
Serial.print(", REV PWR: ");
|
Serial.print(", REV PWR: ");
|
||||||
Serial.println(revPower, 2);
|
Serial.println(revPower, 2);
|
||||||
|
Serial.print("Audio Memory: ");
|
||||||
|
Serial.print(AudioMemoryUsage());
|
||||||
|
Serial.print(",");
|
||||||
|
Serial.println(AudioMemoryUsageMax());
|
||||||
|
Serial.println("----------------------------------------------------------------------");
|
||||||
|
Serial.print("Enabled/Active: PTT: ");
|
||||||
|
Serial.print(TR.pttEnabled() ? "Y" : "N"); Serial.print("/"); Serial.print(TR.pttPressed() ? "Y" : "N");
|
||||||
|
Serial.print(", VOX: ");
|
||||||
|
Serial.print(TR.voxEnabled() ? "Y" : "N"); Serial.print("/"); Serial.print(TR.voxActivated() ? "Y" : "N");
|
||||||
|
Serial.print(", Key: ");
|
||||||
|
Serial.print(TR.keyEnabled() ? "Y" : "N"); Serial.print("/"); Serial.print(TR.keyPressed() ? "Y" : "N");
|
||||||
|
Serial.print(", CAT: ");
|
||||||
|
Serial.print(TR.catEnabled() ? "Y" : "N"); Serial.print("/"); Serial.print(TR.catActivated() ? "Y" : "N");
|
||||||
|
Serial.println();
|
||||||
|
Serial.print("I2C Command/Response: ");
|
||||||
|
for (int i = 0x50; i <= 0x59; i++) {
|
||||||
|
Serial.print(i, HEX); Serial.print(": ");
|
||||||
|
Serial.print(i2cCmdCounter[i - 0x50]); Serial.print("/");
|
||||||
|
Serial.print(i2cRespCounter[i - 0x50]); Serial.print(", ");
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TR.update();
|
|
||||||
|
|
||||||
if (isTX) {
|
if (isTX) {
|
||||||
calcVSWR = Sensors.VSWR();
|
calcVSWR = Sensors.VSWR();
|
||||||
scaledVSWR = byte(Sensors.scaledVSWR());
|
scaledVSWR = byte(Sensors.scaledVSWR());
|
||||||
@@ -521,14 +640,14 @@ void loop()
|
|||||||
// Send forward power.
|
// Send forward power.
|
||||||
if (L_fwdPower != fwdPower) {
|
if (L_fwdPower != fwdPower) {
|
||||||
L_fwdPower = fwdPower;
|
L_fwdPower = fwdPower;
|
||||||
sendCommandL('m', fwdPower * 100); // watts x 100?
|
sendCommandL('m', int(fwdPower * 100.0)); // watts x 100?
|
||||||
sendCommand1Num('m', 2);
|
sendCommand1Num('m', 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send reverse power.
|
// Send reverse power.
|
||||||
//if (L_revPower != revPower) {
|
//if (L_revPower != revPower) {
|
||||||
// L_revPower = revPower;
|
// L_revPower = revPower;
|
||||||
// sendCommandL('m', revPower * 100); // watts x 100?
|
// sendCommandL('m', int(revPower * 100.0)); // watts x 100?
|
||||||
// sendCommand1Num('m', 2);
|
// sendCommand1Num('m', 2);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
@@ -566,6 +685,8 @@ void loop()
|
|||||||
forwardData();
|
forwardData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Rig.isCW()) return; // In CW, the ADC measurement messes with the timing. So need to use interrupts on the Keyer, and/or continuous ADC.
|
||||||
|
|
||||||
if (sinceADCMillis > adcIntervalMillis) {
|
if (sinceADCMillis > adcIntervalMillis) {
|
||||||
// Do stuff that we do once per ADC interval--ADC colllection.
|
// Do stuff that we do once per ADC interval--ADC colllection.
|
||||||
// TODO: debug output (frame skipping / utilization).
|
// TODO: debug output (frame skipping / utilization).
|
||||||
@@ -582,6 +703,8 @@ void loop()
|
|||||||
//forwardData();
|
//forwardData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if (Rig.isCW()) return;
|
||||||
|
|
||||||
// Check Response Command
|
// Check Response Command
|
||||||
if (responseCommand > 0 && sinceForward > LAST_TIME_INTERVAL)
|
if (responseCommand > 0 && sinceForward > LAST_TIME_INTERVAL)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user