Significant updates. Compiles and works, though not test significantly nor assumed to be particularly robust. I2C comms between Raduino and TeensyDSP. Some amount of functioning CAT. Haven't tried with any applications e.g. WSJT-X.

This commit is contained in:
Rob French 2021-02-19 01:39:25 -06:00
parent 1bca18c3e1
commit 119902b1e0
15 changed files with 641 additions and 441 deletions

1
Raduino/Debug.h Symbolic link
View File

@ -0,0 +1 @@
../TeensyDSP/Debug.h

View File

@ -337,7 +337,7 @@ byte delay_background(unsigned delayTime, byte fromType){ //fromType : 4 autoCWK
return 1;
//Check PTT while auto Sending
autoSendPTTCheck();
//autoSendPTTCheck();
//Check_Cat(3);
}
@ -1449,6 +1449,7 @@ void setup()
factory_alignment();
#endif
rigState.begin();
}
//Auto save Frequency and Mode with Protected eeprom life by KD8CEC
@ -1473,8 +1474,6 @@ void checkAutoSaveFreqMode()
saveCheckTime = 0; //for reduce cpu use rate
}
}
rigState.begin();
}
void loop(){

View File

@ -296,7 +296,7 @@ void cwKeyer(void){
return; //Tx stop control by Main Loop
}
Check_Cat(2);
//Check_Cat(2);
} //end of while
// } //end of elese
}

View File

@ -994,7 +994,9 @@ char checkCountSMeter = 0;
void idle_process()
{
// KC4UPR 2021-02-05 added update process for Raduino-TeensyDSP coordination
rigState.update();
rigState.send_RIGINF();
delay(1);
rigState.receive_RIGINF();
//updateStateFromRaduino(rigState);
//doRaduinoToTeensy(&rigState);
//updateRaduinoFromState(rigState);

View File

@ -263,7 +263,7 @@ void menuCHMemory(int btn, byte isMemoryToVfo){
}
}
Check_Cat(0); //To prevent disconnections
//Check_Cat(0); //To prevent disconnections
} //end of while (knob)
if (selectChannel < 20 && selectChannel >= 0)
@ -697,7 +697,7 @@ int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnob
}
}
Check_Cat(0); //To prevent disconnections
//Check_Cat(0); //To prevent disconnections
}
return targetValue;
@ -1290,7 +1290,7 @@ void doMenu(){
default :
menuExit(btnState); break;
} //end of switch
Check_Cat(0); //To prevent disconnections
//Check_Cat(0); //To prevent disconnections
} //end of while
//****************************************************************************
@ -1690,7 +1690,7 @@ void menuSetupCarrier(int btn){
si5351bx_setfreq(0, usbCarrier);
printCarrierFreq(usbCarrier);
Check_Cat(0); //To prevent disconnections
//Check_Cat(0); //To prevent disconnections
delay(100);
}

Binary file not shown.

View File

@ -28,18 +28,19 @@ UBitxDSP DSP;
//static struct {
// GUItool: begin automatically generated code
AudioInputUSB usbIn; //xy=227,290
AudioInputI2S lineIn; //xy=235,182
AudioAnalyzeRMS usbInRMS_R; //xy=350,380
AudioAnalyzeRMS usbInRMS_L; //xy=409,341
AudioAnalyzeRMS lineInRMS; //xy=461,222
AudioMixer4 rxAudio; //xy=492,96
AudioMixer4 txAudio; //xy=496,284
AudioFilterFIR rxFilter; //xy=657,88
AudioAmplifier usbOutAmp; //xy=822,84
AudioAmplifier lineOutAmp; //xy=823,147
AudioOutputI2S lineOut; //xy=1040,279
AudioOutputUSB usbOut; //xy=1042,240
AudioInputUSB usbIn; //xy=153,341
AudioInputI2S lineIn; //xy=161,233
AudioAnalyzeRMS usbInRMS_R; //xy=276,431
AudioAnalyzeRMS usbInRMS_L; //xy=335,392
AudioAnalyzeRMS lineInRMS; //xy=387,273
AudioMixer4 rxAudio; //xy=418,147
AudioMixer4 txAudio; //xy=422,335
AudioFilterFIR rxFilter; //xy=583,139
AudioAmplifier usbOutAmp; //xy=748,135
AudioAmplifier lineOutAmp; //xy=749,198
AudioAmplifier usbBypassAmp; //xy=756,261
AudioOutputI2S lineOut; //xy=966,330
AudioOutputUSB usbOut; //xy=968,291
AudioConnection patchCord1(usbIn, 0, txAudio, 1);
AudioConnection patchCord2(usbIn, 0, usbInRMS_L, 0);
AudioConnection patchCord3(usbIn, 1, usbInRMS_R, 0);
@ -47,13 +48,14 @@ AudioConnection patchCord4(lineIn, 0, rxAudio, 0);
AudioConnection patchCord5(lineIn, 1, txAudio, 0);
AudioConnection patchCord6(lineIn, 1, lineInRMS, 0);
AudioConnection patchCord7(rxAudio, rxFilter);
AudioConnection patchCord8(rxAudio, 0, usbOut, 1);
AudioConnection patchCord8(rxAudio, usbBypassAmp);
AudioConnection patchCord9(txAudio, 0, lineOut, 1);
AudioConnection patchCord10(rxFilter, usbOutAmp);
AudioConnection patchCord11(rxFilter, lineOutAmp);
AudioConnection patchCord12(usbOutAmp, 0, usbOut, 0);
AudioConnection patchCord13(lineOutAmp, 0, lineOut, 0);
AudioControlSGTL5000 audioCtrl; //xy=501,425
AudioConnection patchCord14(usbBypassAmp, 0, usbOut, 1);
AudioControlSGTL5000 audioCtrl; //xy=427,476
// GUItool: end automatically generated code
//} audio;
@ -99,10 +101,11 @@ void UBitxDSP::begin() {
// SETUP THE AUDIO OUTPUTS
// Line Output (RX)
lineOutAmp.gain(0.0);
lineOutAmp.gain(1.0);
// USB Output (RX)
usbOutAmp.gain(0.0);
usbOutAmp.gain(1.0);
usbBypassAmp.gain(1.0);
// Rig (Line) Output (TX)
@ -123,6 +126,9 @@ void UBitxDSP::begin() {
state.voxDelay[TX_USB_IN_R_VOX] = TX_USB_IN_R_VOX_DELAY;
state.voxTimeout[TX_USB_IN_R_VOX] = 0;
// Setup the RX Filter.
setRxFilter(300, 3000);
sinceLastUpdate = 0;
}

View File

@ -8,11 +8,13 @@
#define DBGPRINTLN(MSG) do { Serial.print("DBG: "); Serial.println(MSG); } while (0)
#define DBGNEWLINE() do { Serial.println(); } while (0)
#define DBGCMD(CMD) do { Serial.print("DBG: "); Serial.println(#CMD); CMD; } while (0)
#define IFDEBUG(CMD) do { CMD; } while (0)
#else
#define DBGPRINT(MSG) do {} while (0)
#define DBGPRINTLN(MSG) do {} while (0)
#define DBGNEWLINE() do {} while (0)
#define DBGCMD(CMD) do { CMD; } while (0)
#define IFDEBUG(CMD) do {} while (0)
#endif
#endif

View File

@ -15,31 +15,31 @@ class UBitxRig {
inline bool isVFOA() const { return radState.isVFOA(); }
inline bool isVFOB() const { return radState.isVFOB(); }
inline bool isSplit() const { return radState.isSplit(); }
inline bool isRITOn() const { return radState.isRITOn(); }
inline bool isXITOn() const { return radState.isXITOn(); }
inline bool isModeCW() const { return radState.isCW() && radState.isUSB(); }
inline bool isModeCWR() const { return radState.isCW() && radState.isLSB(); }
inline bool isModeUSB() const { return radState.isUSB() && !radState.isCW(); }
inline bool isModeLSB() const { return radState.isLSB() && !radState.isCW(); }
inline bool isRIT() const { return radState.isRIT(); }
inline bool isXIT() const { return radState.isXIT(); }
inline bool isModeCWAny() const { return radState.isModeCWAny(); }
inline bool isModeCW() const { return radState.isModeCW(); }
inline bool isModeCWR() const { return radState.isModeCWR(); }
inline bool isModeUSB() const { return radState.isModeUSB(); }
inline bool isModeLSB() const { return radState.isModeLSB(); }
inline bool isAI() const { return autoInfo; }
inline void setFreqA(unsigned freq) { catState.setFreqA(freq); }
inline void setFreqB(unsigned freq) { catState.setFreqB(freq); }
inline void setRIT(int freq) { catState.setRIT(freq); }
inline void setXIT(int freq) { catState.setXIT(freq); }
inline void selectVFOA() { catState.selectVFOA(); }
inline void selectVFOB() { catState.selectVFOA(); }
inline void toggleVFO() { catState.toggleVFO(); }
inline void setVFOA() { catState.setVFOA(); }
inline void setVFOB() { catState.setVFOB(); }
inline void setSplitOn() { catState.setSplitOn(); }
inline void setSplitOff() { catState.setSplitOff(); }
inline void setRITOn() { catState.setRITOn(); }
inline void setRITOff() { catState.setRITOff(); }
inline void setXITOn() { catState.setXITOn(); }
inline void setXITOff() { catState.setXITOff(); }
inline void setModeCW() { catState.setUSB(); catState.setCW(); }
inline void setModeCWR() { catState.setLSB(); catState.setCW(); }
inline void setModeUSB() { catState.setUSB(); catState.setCW(); }
inline void setModeLSB() { catState.setLSB(); catState.setCW(); }
inline void setCW() { catState.setCW(); }
inline void setCWR() { catState.setCWR(); }
inline void setUSB() { catState.setUSB(); }
inline void setLSB() { catState.setLSB(); }
inline void aiOn() { autoInfo = true; }
inline void aiOff() { autoInfo = false; }

View File

@ -1,13 +1,62 @@
#include ""
/*!
* @file RigState.cpp
*
* @mainpage uBITX V5X Software - RigState
*
* @section introsec Introduction
*
* TBD
*
* @section dependencies Dependencies
*
* TBD
*
* @section author Author
*
* Written by Rob "Scrape" French, KC4UPR
*
* @section license License
*
* TBD
*/
/**********************************************************************/
// Raduino externs -- generally defined in Raduino.ino or ubitx.h
#include "Debug.h"
#include "RigState.h"
/***********************************************************************
* COMMON FUNCTIONS
*
* The following are all common to RigState objects, whether on the
* Raduino or on the TeensyDSP.
**********************************************************************/
static uint32_t zeroes[1] = {0}; // used to transmit zeroes
/*!
* @brief Begin using the RigState object. In order to force an
* initial update (i.e. sending current state to the remote
* device), all fields are initially marked dirty.
*/
void UBitxRigState::begin() {
setDirty();
}
/***********************************************************************
* RADUINO FUNCTIONS
*
* The following are specific to the Raduino implementation. Note that
* this depends on the use of the TEENSYDUINO #define, which may result
* in a fragile implementation for other development environments (e.g.
* if the normal Arduino IDE is not being used).
**********************************************************************/
#ifndef TEENSYDUINO
#include <Wire.h>
#include "ubitx.h"
#include "ubitx_eemap.h"
extern unsigned long frequency;
extern unsigned long frequency, ritRxFrequency, ritTxFrequency;
extern unsigned long vfoA;
extern unsigned long vfoB;
extern char cwMode;
@ -15,48 +64,115 @@ extern char isUSB;
extern char vfoActive;
extern char ritOn;
extern char splitOn;
extern char inTx;
void setFrequency(unsigned long);
/*!
* @brief Write dirty fields from the provided rig state, out to the
* Raduino variables.
* @param r
* Reference to a RigState object that will be used to update
* the Raduino variables.
* @brief Send the RigState from the Raduino to the TeensyDSP. The
* basic process is: (1) read in any updated (dirty) data
* from the Raduino's state variables; (2) transmit the dirty
* data to the TeensyDSP; (2a) for clean data, zeroes are
* transmitted; (3) mark all data as clean.
*/
void writeDirty(const RigState& r) {
// VFO A frequency
if (r.isDirty(VFOA_WORD)) {
if (vfoActive == VFO_A) {
setFrequency(r.getFreqA());
void UBitxRigState::send_RIGINF() {
readDirty();
Wire.beginTransmission(I2CMETER_ADDR);
Wire.write(I2CMETER_RIGINF);
for (RigStateWord i = DIRTY_WORD; i < NUM_WORDS; i++) {
if (i == DIRTY_WORD || isDirty(i)) {
// always send the current dirty bits
// or, bytes for updated (dirty) fields
Wire.write((byte*)&data[i], sizeof(uint32_t));
} else {
vfoA = r.getFreqA();
// otherwise, send out zeroes
Wire.write((byte*)&zeroes, sizeof(uint32_t));
//----------------------------------------------------------------
// NOTE: I am sending these zeroed out fields under a possibly
// mistaken assumption that in doing so, I will be sending a
// constant voltage on the SDA line most of the time, i.e. no
// bit changes, and so this will help reduce noise generated by
// I2C traffic (since most of the time there will be no updates.)
//----------------------------------------------------------------
}
}
Wire.endTransmission();
IFDEBUG( serialHexState("Sent") );
//IFDEBUG( serialPrettyState("Sent") );
setClean();
}
// delay(1); // 1ms - some delay required between ending transmission and requesting?
/*!
* @brief Receive the RigState from the TeensyDSP. This generally
* reflects changes due to CAT transmission to the TeensyDSP.
* @param numBytes
* Number of bytes received from the TeensyDSP.
*/
void UBitxRigState::receive_RIGINF(int numBytes) {
// Retrieve all of the deltas. Mark any received fields as dirty. It
// is assumed that send_RIGINF() was called immedaitely before this,
// so the fields are already clean.
byte* ptr = (byte*)&data;
Wire.requestFrom(I2CMETER_ADDR, sizeof(data));
for (RigStateWord i = DIRTY_WORD; i < NUM_WORDS && Wire.available(); i++) {
for (size_t j = 0; j < sizeof(uint32_t) && Wire.available(); j++) {
byte incomingByte = Wire.read();
if (i == DIRTY_WORD || isDirty(i)) {
// always overwrite the dirty bits
// and, update bytes for fields marked dirty
*ptr = incomingByte;
}
ptr++;
}
}
writeDirty();
IFDEBUG( serialHexState("Rcvd") );
//IFDEBUG( serialPrettyState("Rcvd") );
setClean(); // They get marked dirty as req'd during readDirty().
}
/*!
* @brief Write dirty fields from the RigState out to the Raduino
* variables.
*/
void UBitxRigState::writeDirty() {
// VFO A frequency
if (isDirty(VFOA_WORD)) {
if (vfoActive == VFO_A) {
setFrequency(getFreqA());
} else {
vfoA = getFreqA();
}
}
// VFO B frequency
if (r.isDirty(VFOB_WORD)) {
if (isDirty(VFOB_WORD)) {
if (vfoActive == VFO_B) {
setFrequency(r.getFreqB());
setFrequency(getFreqB());
} else {
vfoB = r.getFreqB();
vfoB = getFreqB();
}
}
// RIT and XIT frequencies
if (r.isDirty(OFFSETS_WORD)) {
if (isDirty(OFFSETS_WORD)) {
// RIT
ritRxFrequency = r.getRIT() + ritTxFrequency;
if ((ritOn == 1) && (inTx == 0)) {
setFrequency(ritRxFrequency);
ritRxFrequency = getRIT() + ritTxFrequency;
if (ritOn == 1) {
if (inTx == 0) {
setFrequency(ritRxFrequency);
} else {
setFrequency(ritTxFrequency);
}
}
// XIT - TODO
}
// VFO A/B selection
if (r.isDirty(FLAGS_WORD)) {
if (isDirty(FLAGS_WORD)) {
char prev = vfoActive;
vfoActive = r.isVFOA() ? VFO_A : VFO_B;
vfoActive = isVFOA() ? VFO_A : VFO_B;
if (vfoActive != prev) {
if (vfoActive == VFO_A) {
if (vfoA != frequency) {
@ -70,11 +186,11 @@ void writeDirty(const RigState& r) {
}
// Split on/off
splitOn = r.isSplit() ? 1 : 0;
splitOn = isSplit() ? 1 : 0;
// RIT on/off
prev = ritOn;
ritOn = r.isRIT() ? 1 : 0;
ritOn = isRIT() ? 1 : 0;
if (ritOn != prev) {
if ((ritOn == 1) && (inTx == 0)) {
setFrequency(ritRxFrequency);
@ -86,10 +202,10 @@ void writeDirty(const RigState& r) {
// Mode
prev = (cwMode << 1) | isUSB;
isUSB = r.isUSB() ? 1 : 0;
if (r.isCW()) {
isUSB = isModeUSB() ? 1 : 0;
if (isModeCW()) {
cwMode = 2; // 2 = cwu
} else if (r.isCWR()) {
} else if (isModeCWR()) {
cwMode = 1; // 1 = cwl
} else {
cwMode = 0; // 0 = no cw
@ -101,274 +217,200 @@ void writeDirty(const RigState& r) {
}
/*!
* @brief Read current Raduino variables into the provided RigState
* (if they are dirty) and set the appropriate dirty flags.
* @brief Read current Raduino variables into the RigState
* (if they are changed) and set the appropriate dirty flags.
* @param r
* RigState reference to put the values into.
*/
void readDirty(RigState& r) {
unsigned freq;
void UBitxRigState::readDirty() {
unsigned long freq;
short offset;
// VFO A frequency
freq = (vfoActive == VFO_A) ? frequency : vfoA;
if (r.getFreqA() != freq) {
r.setFreqA(freq);
r.setDirty(VFOA_WORD);
if (getFreqA() != freq) {
setFreqA(freq);
}
// VFO B frequency
freq = (vfoActive == VFO_B) ? frequency : vfoB;
if (r.getFreqB() != freq) {
r.setFreqB(freq);
r.setDirty(VFOB_WORD);
if (getFreqB() != freq) {
setFreqB(freq);
}
// RIT frequency
offset = ritRxFrequency - frequency;
if (r.getRIT() != offset) {
r.setRIT(offset);
r.setDirty(OFFSETS_WORD);
if (inTx) {
offset = ritRxFrequency - ritTxFrequency;
} else {
offset = frequency - ritTxFrequency;
}
if (getRIT() != offset) {
setRIT(offset);
}
// XIT frequency
offset = 0; // xitRxFrequency - frequency;
if (r.getXIT() != offset) {
r.setXIT(offset);
r.setDirty(OFFSETS_WORD);
if (getXIT() != offset) {
setXIT(offset);
}
bool dirty = false;
// VFO A/B selection
if (r.isVFOA() && vfoActive == VFO_B) {
r.setVFOB();
dirty = true;
} else if (r.isVFOB() && vfoActive == VFO_A) {
r.setVFOA();
dirty = true;
if (isVFOA() && vfoActive == VFO_B) {
setVFOB();
} else if (isVFOB() && vfoActive == VFO_A) {
setVFOA();
}
// Split selection
if (r.isSplit() && splitOn == 0) {
r.setSplitOff();
dirty = true;
} else if (!r.isSplit() && splitOn != 0) {
r.setSplitOn();
dirty = true;
if (isSplit() && splitOn == 0) {
setSplitOff();
} else if (!isSplit() && splitOn != 0) {
setSplitOn();
}
// RIT selection
if (r.isRIT() && ritOn == 0) {
r.setRITOff();
dirty = true;
} else if (!r.isRIT() && ritOn != 0) {
r.setRITOn();
dirty = true;
if (isRIT() && ritOn == 0) {
setRITOff();
} else if (!isRIT() && ritOn != 0) {
setRITOn();
}
// XIT selection
r.setXITOff();
//setXITOff();
// TODO
// Mode
char prev = (r.isCW() ? 4 : 0) | (r.isCWR() ? 2 : 0) | (r.isUSB() ? 1 : 0);
char prev = (isModeCW() ? 4 : 0) | (isModeCWR() ? 2 : 0) | (isModeUSB() ? 1 : 0);
char curr = (cwMode << 1) | isUSB;
if (curr != prev) {
if (cwMode == 2) {
r.setCW();
setCW();
} else if (cwMode == 1) {
r.setCWR();
setCWR();
} else {
if (isUSB) {
r.setUSB();
setUSB();
} else {
r.setLSB();
setLSB();
}
}
dirty = true;
}
if (dirty) r.setDirty(FLAGS_WORD);
}
/***********************************************************************
* TEENSYDSP FUNCTIONS
*
* The following are specific to the TeensyDSP implementation. Note
* that this depends on the use of the TEENSYDUINO #define, which may
* result in a fragile implementation for other development environments
* (e.g. if the normal Arduino IDE is not being used).
**********************************************************************/
#else
#include <i2c_t3.h>
/*!
* @brief Receive RIGINF data from the Raduino. This method should
* be called on the TeensyDSP 'radState' (Raduino state)
* instance, when a RIGINF signal is received via I2C. It
* receives the incoming data from the Raduino and updates the
* state.
*/
void UBitxRigState::receive_RIGINF(int numBytes) {
byte* ptr = (byte*)&data;
setClean(); // we'll get new dirty bits via the I2C message
for (RigStateWord i = DIRTY_WORD; i < NUM_WORDS && Wire1.available(); i++) {
for (size_t j = 0; j < sizeof(uint32_t) && Wire1.available(); j++) {
byte incomingByte = Wire1.read();
if (i == DIRTY_WORD || isDirty(i)) {
// always overwrite the dirty bits
// and, update bytes for fields marked dirty
*ptr = incomingByte;
}
ptr++;
}
}
IFDEBUG( serialHexState("Rcvd") );
IFDEBUG( serialPrettyState("Rcvd") );
}
/**********************************************************************/
/*!
* @brief Handle a RIGINF signal from the Raduino. This method should
* be called on the TeensyDSP 'catState' (CAT state)
* instance, when a RIGINF signal is received via I2C. It
* sends a response to the Raduino via I2C, using the Wire1
* interface.
*/
void UBitxRigState::send_RIGINF() {
for (RigStateWord i = DIRTY_WORD; i < NUM_WORDS; i++) {
if (i == DIRTY_WORD || isDirty(i)) {
// always send the current dirty bits
// or, bytes for updated (dirty) fields
Wire1.write((byte*)&data[i], sizeof(uint32_t));
} else {
// otherwise, send out zeroes
Wire1.write((byte*)&zeroes, sizeof(uint32_t));
//----------------------------------------------------------------
// NOTE: I am sending these zeroed out fields under a possibly
// mistaken assumption that in doing so, I will be sending a
// constant voltage on the SDA line most of the time, i.e. no
// bit changes, and so this will help reduce noise generated by
// I2C traffic (since most of the time there will be no updates.)
//----------------------------------------------------------------
}
}
IFDEBUG( serialHexState("Sent") );
IFDEBUG( serialPrettyState("Sent") );
setClean(); // now that we've sent them, they're clean
//--------------------------------------------------------------------
// TODO: Need to look at possibly merging the two states together at
// this point. The purpose would be to minimize the turnaround time
// for getting the most recent data to a CAT response.
//--------------------------------------------------------------------
}
#endif
/**********************************************************************/
#ifdef DEBUG
BaseField* raduinoFields[WIREBUS_NUM_FIELDS] = {
new Field<readNone, writeNone>(),
new Field<readVFOA, writeVFOA>(),
new Field<readVFOB, writeVFOB>(),
new Field<readRIT, writeRIT>(),
new Field<readXIT, writeXIT>(),
new Field<readFlags, writeFlags>(),
};
char debugString[81] = {'\0'};
/**********************************************************************/
RigState::RigState(): RigState(raduinoFields, WIREBUS_NUM_FIELDS) {}
/*!
* @brief Begin using the RigState object. In order to force an
* update (e.g. sending current state to the remote device),
* all fields are marked dirty.
*/
void RigState::begin() {
for (byte i = 0; i < numFields; i++) {
if (read(i)) {
makeDirty(i);
}
}
void UBitxRigState::serialHexState(const char* label = "RigState") {
Serial.print(label);
sprintf(debugString, ": %#010lx, %#010lx, %#010lx, %#010lx, %#010lx",
data[DIRTY_WORD], data[VFOA_WORD], data[VFOB_WORD], data[OFFSETS_WORD], data[FLAGS_WORD]);
Serial.println(debugString);
}
void updateRaduinoState(RigState& r) {
writeDirty(r);
Wire.beginTransmission(I2CMETER_ADDR);
Wire.write(I2CMETER_RIGINF);
for (RigStateWord i = 0; i < NUM_WORDS; i++) {
Wire.write((byte*)&r.data, sizeof(r.data)); // - write the field data
r.setClean(i);
}
Wire.endTransmission();
delay(1); // 1ms - some delay required between ending transmission and requesting?
// Retrieve all of the deltas. Mark any received field as dirty.
Wire.requestFrom(I2CMETER_ADDR, numBytes);
bool doRead = true;
int index = -1;
byte* ptr;
while (Wire.available()) {
byte b = Wire.read();
if (index == -1) {
if (numFields > b) {
ptr = data(b);
field[b].dirty = true;
numDirty++;
index = 0;
} else {
doRead = false;
}
} else {
if (doRead) {
ptr[index] = b;
}
if (++index == 4) {
index = -1;
doRead = true;
}
}
}
// Perform the corresponding update for each dirty field.
for (byte i = 0; i < numFields; i++) {
if (field[i].dirty) {
write(i);
field[i].dirty = false;
numDirty--;
}
}
void UBitxRigState::serialPrettyState(const char* label = "RigState") {
Serial.println(label);
sprintf(debugString, "VFO A : %011ld %1c / VFO B : %011ld %1c",
getFreqA(), isDirty(VFOA_WORD) ? 'D' : ' ', getFreqB(), isDirty(VFOB_WORD) ? 'D' : ' ');
Serial.println(debugString);
sprintf(debugString, "RIT : %011ld %1c / XIT : %011ld %1c",
getRIT(), isDirty(OFFSETS_WORD) ? 'D' : ' ', getXIT(), isDirty(OFFSETS_WORD) ? 'D' : ' ');
Serial.println(debugString);
sprintf(debugString, "Split? %1c / VFO? %1c / RIT? %1c / XIT? %1c / Mode? %3s",
isSplit() ? 'Y' : 'N', isVFOA() ? 'A' : 'B', isRIT() ? 'Y' : 'N', isXIT() ? 'Y' : 'N',
isModeUSB() ? "USB" : (isModeLSB() ? "LSB" : (isModeCW() ? "CW " : (isModeCWR() ? "CWR" : " "))));
Serial.println(debugString);
}
/**********************************************************************/
/*!
* @brief Handle a RIGINF signal from the Raduino. This method should
* be called on the TeensyDSP 'radState' (Raduino state)
* instance, when a RIGINF signal is received via I2C. It
* receives the incoming data from the Raduino.
*/
void RigState::receive_RIGINF() {
// 1st (-1) byte read should be a field index.
// 2nd (0) thru 5th (3) bytes are bytes of the field.
// We'll read as many fields as the Raduino sends.
bool doRead = true;
int index = -1;
byte* ptr;
while (Wire1.available()) {
byte b = Wire1.read();
if (index == -1) {
if (numFields > b) {
ptr = data(b);
makeDirty(b);
index = 0;
} else {
doRead = false;
}
} else {
if (doRead) {
ptr[index] = b;
}
if (++index == 4) {
index = -1;
doRead = true;
}
}
}
}
#endif
/**********************************************************************/
/*!
* @brief Handle a RIGINF signal from the Raduino. This method should
* be called on the TeensyDSP 'radState' (Raduino state)
* instance, when a RIGINF signal is received via I2C. It
* sends a response to the Raduino
*/
void RigState::send_RIGINF(byte numBytes, RigState& catState) {
// Now we need to determine the differences from the other state (i.e.
// from the catState) and send those differences.
byte rigRegBytes = 0;
for (byte i = 0; i < numFields; i++) {
if (isDirty(i) && !catState.isDirty(i)) {
catState.field[i]->data = field[i]->data;
makeClean(i);
} else if (catState.isDirty(i)) {
field[i]->data = catState.field[i]->data;
makeClean(i);
rigRegBytes += (sizeof(byte) + sizeof(uint32_t)); // size of field ID and data
}
}
for (byte i = 0; i < numBytes; i++) {
Wire1.write(rigReqBytes);
}
}
/**********************************************************************/
/*!
* @brief Handle a RIGREQ signal from the Raduino. This method should
* be called on the TeensyDSP 'catState' (CAT state) instance,
* when a RIGREQ signal is received via I2C. It handles
* sending the changed fields.
*/
void RigState::respondRIGREQ(byte numBytes) {
byte bytesSent = 0;
for (byte i = 0; i < numFields; i++) {
if (isDirty(i) && (dataSize(i) + sizeof(byte) <= numBytes - bytesSent)) { // Write each field that is dirty to the bus.
Wire1.write(i); // - write the field number/ID
Wire1.write(data(i), dataSize(i)); // - write the field data
makeClean(i);
bytesSent += dataSize(i) + sizeof(byte);
}
}
// Don't know if this is necessary, but if we haven't written enough
// bytes yet, we'll write out some zeroes.
for (byte i = bytesSent; i < numBytes; i++) {
Wire1.write(0);
}
}
/**********************************************************************/
#ifndef TEENSYDUINO
RigState rigState;
UBitxRigState _rigState;
UBitxRigState& rigState = _rigState;
#endif
/**********************************************************************
* EOF *
/***********************************************************************
* EOF
**********************************************************************/

View File

@ -1,3 +1,7 @@
/*!
* @file RigState.h
*/
#ifndef __RigState_h__
#define __RigState_h__
@ -11,6 +15,12 @@
#define UBITX_USB_FLAG 0x00000020
#define UBITX_TX_FLAG 0x00000040
#ifdef TEENSYDUINO
#define DISABLEINTS(CMD) do { noInterrupts(); CMD; interrupts(); } while (0)
#else
#define DISABLEINTS(CMD) do { CMD; } while (0)
#endif
enum RigStateWord {
DIRTY_WORD = 0,
VFOA_WORD,
@ -20,174 +30,307 @@ enum RigStateWord {
NUM_WORDS
};
inline RigStateWord& operator++(RigStateWord& orig) {
orig = static_cast<RigStateWord>(orig + 1);
// NOTE: Will overflow...
return orig;
}
inline RigStateWord operator++(RigStateWord& orig, int) {
RigStateWord rVal = orig;
++orig;
return rVal;
}
struct UBitxRigState {
uint32_t data[RigStateWord.NUM_WORDS] = {0};
volatile uint32_t data[NUM_WORDS] = {0};
void begin();
void send_RIGINF();
void receive_RIGINF(int numBytes = sizeof(data));
/*!
* @brief Set the dirty bit for for the specified word.
* @brief Set the dirty bit for the specified word.
*
* @param w
* The word to mark as dirty.
*/
inline void setDirty(RigStateWord w) {
data[i] |= w < NUM_WORDS ? 1 << w : 0;
data[DIRTY_WORD] |= w < NUM_WORDS ? 1 << w : 0;
}
/*!
* @brief Set the dirty bits for all words.
*/
inline void setDirty() { DISABLEINTS( data[DIRTY_WORD] = 0xFFFFFFFF ); }
/*!
* @brief Clear the dirty bit for the specified word.
*
* @param w
* The word to mark as clean.
*/
inline void setClean(RigStateWord w) {
data[i] &= ~(w < NUM_WORDS ? 1 << w : 0);
data[DIRTY_WORD] &= ~(w < NUM_WORDS ? 1 << w : 0);
}
/*!
* @brief Clear the dirty bits for all words.
*/
inline void setClean() { DISABLEINTS( data[DIRTY_WORD] = 0 ); }
/*!
* @brief Check whether the specified word is clean.
*
* @param w
* The word to check for clean status.
*
* @return True if the word is clean.
*/
inline bool isClean(RigStateWord w) {
bool clean;
DISABLEINTS( clean = ((1 << w) & data[DIRTY_WORD]) > 0 ? false : true );
return clean;
}
/*!
* @brief Check whether the data is clean (as a whole).
*
* @return True if the data is clean (no dirty fields).
*/
inline bool isClean() {
bool clean;
DISABLEINTS( clean = data[DIRTY_WORD] == 0 );
return clean;
}
/*!
* @brief Check whether the specified word is dirty.
*
* @param w
* The word to check for dirty status.
*
* @return True if the word is dirty.
*/
inline bool isDirty(RigStateWord w) {
return (1 << w) & data[DIRTY_WORD] > 0 ? true : false;
bool dirty;
DISABLEINTS( dirty = ((1 << w) & data[DIRTY_WORD]) > 0 ? true : false );
return dirty;
}
/*!
* @brief Check whether the data is dirty (as a whole).
*
* @return True if the data is dirty (at least one dirty field).
*/
inline bool isDirty() {
bool dirty;
DISABLEINTS( dirty = data[DIRTY_WORD] != 0 );
return dirty;
}
inline void setFreqA(uint32_t freq) { data[VFOA_WORD] = freq; }
inline uint32_t getFreqA() const { return data[VFOA_WORD]; }
inline void getFreqB(uint32_r freq) { data[VFOB_WORD] = freq; }
inline uint32_t getFreqB() const { return data[VFOB_WORD]; }
inline void setRIT(int16_t offset) { data[OFFSETS_WORD] = (offset << 16) | (0x0000FFFF & data[OFFSETS_WORD]); }
inline int16_t getRIT() const { return data[OFFSETS_WORD] >> 16; }
inline void setXIT(int16_t offset) { data[OFFSETS_WORD] = (0xFFFF0000 & data[OFFSETS_WORD]) | offset;
inline int16_t getXIT() const { return 0x0000FFFF & data[OFFSETS_WORD]; }
inline void setVFOA() { data[FLAGS_WORD] &= ~UBITX_VFOB_FLAG; }
inline void setVFOB() { data[FLAGS_WORD] |= UBITX_VFOB_FLAG; }
inline bool isVFOA() const { return data[FLAGS_WORD] & UBITX_VFOB_FLAG ? false : true; }
inline bool isVFOB() const { return data[FLAGS_WORD] & UBITX_VFOB_FLAG ? true : false; }
inline void setSplitOn() { data[FLAGS_WORD] |= UBITX_SPLIT_FLAG; }
inline void setSplitOff() { data[FLAGS_WORD] &= ~UBITX_SPLIT_FLAG; }
inline bool isSplit() const { data[FLAGS_WORD] & UBITX_SPLIT_FLAG ? true : false; }
inline void setRITOn() { data[FLAGS_WORD] |= UBITX_RIT_FLAG; }
inline void setRITOff() { data[FLAGS_WORD] &= ~UBITX_RIT_FLAG; }
inline bool isRIT() const { data[FLAGS_WORD] & UBITX_RIT_FLAG ? true : false; }
inline void setXITOn() { data[FLAGS_WORD] |= UBITX_XIT_FLAG; }
inline void setXITOff() { data[FLAGS_WORD] &= ~UBITX_XIT_FLAG; }
inline bool isXIT() const { data[FLAGS_WORD] & UBITX_XIT_FLAG ? true : false; }
inline void setUSB() { data[FLAGS_WORD] |= UBITX_USB_FLAG; data[FLAGS_WORD] &= ~UBITX_CW_FLAG; }
inline void setLSB() { data[FLAGS_WORD] &= ~UBITX_USB_FLAG; data[FLAGS_WORD] &= ~UBITX_CW_FLAG; }
inline void setCW() { data[FLAGS_WORD] |= UBITX_USB_FLAG; data[FLAGS_WORD] |= UBITX_CW_FLAG; }
inline void setCWR() { data[FLAGS_WORD] &= ~UBITX_USB_FLAG; data[FLAGS_WORD] |= UBITX_CW_FLAG; }
inline bool isUSB() { return (data[FLAGS_WORD] & UBITX_USB_FLAG > 0) && (data[FLAGS_WORD] & UBITX_CW_FLAG == 0); }
inline bool isLSB() { return (data[FLAGS_WORD] & UBITX_USB_FLAG == 0) && (data[FLAGS_WORD] & UBITX_CW_FLAG == 0); }
inline bool isCW() { return (data[FLAGS_WORD] & UBITX_USB_FLAG > 0) && (data[FLAGS_WORD] & UBITX_CW_FLAG > 0); }
inline bool isCWR() { return (data[FLAGS_WORD] & UBITX_USB_FLAG == 0) && (data[FLAGS_WORD] & UBITX_CW_FLAG > 0); }
};
/*!
* @brief Set the VFO A frequency.
*
* @param freq
* The new frequency in Hz.
*/
inline void setFreqA(uint32_t freq, bool mark = true) {
DISABLEINTS( data[VFOA_WORD] = freq;
if (mark) setDirty(VFOA_WORD) );
}
inline uint32_t getFreqA() const {
uint32_t result;
DISABLEINTS( result = data[VFOA_WORD] );
return result;
}
#ifndef TEENSYDUINO
void mergeDirty(const RigState& r);
/*!
* @brief Set the VFO B frequency.
*
* @param freq
* The new frequency in Hz.
*/
inline void setFreqB(uint32_t freq, bool mark = true) {
DISABLEINTS( data[VFOB_WORD] = freq );
}
inline uint32_t getFreqB() const {
uint32_t result;
DISABLEINTS( result = data[VFOB_WORD] );
return result;
}
inline void setRIT(int16_t offset, bool mark = true) {
DISABLEINTS( data[OFFSETS_WORD] = (int32_t(offset) << 16) | (0x0000FFFF & data[OFFSETS_WORD]);
if (mark) setDirty(OFFSETS_WORD) );
}
inline int16_t getRIT() const {
int16_t result;
DISABLEINTS( result = data[OFFSETS_WORD] >> 16 );
return result;
}
inline void setXIT(int16_t offset, bool mark = true) {
DISABLEINTS( data[OFFSETS_WORD] = (0xFFFF0000 & data[OFFSETS_WORD]) | offset;
if (mark) setDirty(OFFSETS_WORD) );
}
inline int16_t getXIT() const {
int16_t result;
DISABLEINTS( result = 0x0000FFFF & data[OFFSETS_WORD] );
return result;
}
inline void setVFOA(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] &= ~UBITX_VFOB_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline void setVFOB(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] |= UBITX_VFOB_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline bool isVFOA() const {
bool result;
DISABLEINTS( result = data[FLAGS_WORD] & UBITX_VFOB_FLAG ? false : true );
return result;
}
inline bool isVFOB() const {
bool result;
DISABLEINTS( result = data[FLAGS_WORD] & UBITX_VFOB_FLAG ? true : false );
return result;
}
inline void setSplitOn(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] |= UBITX_SPLIT_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline void setSplitOff(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] &= ~UBITX_SPLIT_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline bool isSplit() const {
bool result;
DISABLEINTS( result = data[FLAGS_WORD] & UBITX_SPLIT_FLAG ? true : false );
return result;
}
inline void setRITOn(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] |= UBITX_RIT_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline void setRITOff(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] &= ~UBITX_RIT_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline bool isRIT() const {
bool result;
DISABLEINTS( result = data[FLAGS_WORD] & UBITX_RIT_FLAG ? true : false );
return result;
}
inline void setXITOn(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] |= UBITX_XIT_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline void setXITOff(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] &= ~UBITX_XIT_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline bool isXIT() const {
bool result;
DISABLEINTS( result = data[FLAGS_WORD] & UBITX_XIT_FLAG ? true : false );
return result;
}
inline void setUSB(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] |= UBITX_USB_FLAG;
data[FLAGS_WORD] &= ~UBITX_CW_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline void setLSB(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] &= ~UBITX_USB_FLAG;
data[FLAGS_WORD] &= ~UBITX_CW_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline void setCW(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] |= UBITX_USB_FLAG;
data[FLAGS_WORD] |= UBITX_CW_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline void setCWR(bool mark = true) {
DISABLEINTS( data[FLAGS_WORD] &= ~UBITX_USB_FLAG;
data[FLAGS_WORD] |= UBITX_CW_FLAG;
if (mark) setDirty(FLAGS_WORD) );
}
inline bool isModeUSB() const {
bool result;
DISABLEINTS( result = ((data[FLAGS_WORD] & UBITX_USB_FLAG) > 0) && ((data[FLAGS_WORD] & UBITX_CW_FLAG) == 0) );
return result;
}
inline bool isModeLSB() const {
bool result;
DISABLEINTS( result = ((data[FLAGS_WORD] & UBITX_USB_FLAG) == 0) && ((data[FLAGS_WORD] & UBITX_CW_FLAG) == 0) );
return result;
}
inline bool isModeCWAny() const {
bool result;
DISABLEINTS( result = (data[FLAGS_WORD] & UBITX_CW_FLAG) > 0 );
return result;
}
inline bool isModeCW() const {
bool result;
DISABLEINTS( result = ((data[FLAGS_WORD] & UBITX_USB_FLAG) > 0) && ((data[FLAGS_WORD] & UBITX_CW_FLAG) > 0) );
return result;
}
inline bool isModeCWR() const {
bool result;
DISABLEINTS( result = ((data[FLAGS_WORD] & UBITX_USB_FLAG) == 0) && ((data[FLAGS_WORD] & UBITX_CW_FLAG) > 0) );
return result;
}
#ifdef DEBUG
void serialHexState(const char* label);
void serialPrettyState(const char* label);
#endif
/**********************************************************************/
// NEW IMPLEMENTATION
struct BaseField {
BaseField(): dirty(false), data(0) {}
virtual ~BaseField() = 0;
bool dirty;
uint32_t data;
virtual bool read() = 0;
virtual void write() const = 0;
};
template<typename R, typename W>
struct Field : public BaseField {
/*!
* @brief Using the supplied read function, which should take a
* pointer to data as its input, read from (some source) and
* update the value of data as appropriate. The read
* function should true if the new value is new and hence
* the dirty bit should be marked, false otherwise.
* @return True if data was updated (dirty), false otherwise.
*/
virtual bool read() { return R(&data); }
/*!
* @brief Using the supplied write function, which should take
* data as its input, write data to some destination.
*/
virtual void write() const { W(data); }
};
#define WIREBUS_VFO_A 1
#define WIREBUS_VFO_B 2
#define WIREBUS_RIT_OFS 3
#define WIREBUS_XIT_OFS 4
#define WIREBUS_FLAGS 5
#define WIREBUS_NUM_FIELDS 6
class RigState {
public:
RigState(BaseField** f = NULL, int numf = 0): field(f), numFields(numf), numDirty(0) {}
void begin();
void update();
/*!
* @brief Read in the specified (by index) external value, and use
* it to update the rig state.
*/
inline bool read(byte i) {
return field[i]->read();
}
/*!
* @brief Use the specified (vy index) rig state field to update the
* external value.
*/
inline void write(byte i) {
field[i]->write();
}
inlie bool isDirty(byte i) {
return field[i]->dirty();
}
inline void makeDirty(byte i) {
if (!field[i]->dirty) {
field[i]->dirty = true;
numDirty++;
}
}
inline void makeClean(byte i) {
if (field[i]->dirty) {
field[i]->dirty = false;
numDirty--;
}
}
inline byte* data(byte i) {
return (byte*)(&(field[i]->data));
}
inline int dataSize(byte i) {
return sizeof(field[i]->data);
}
inline unsigned getFreqA() const { return field[WIREBUS_VFO_A]->data; }
inline unsigned getFreqB() const { return field[WIREBUS_VFO_B]->data; }
inline int getRIT() const { return int(field[WIREBUS_VFO_A]->data); }
inline int getXIT() const { return int(field[WIREBUS_VFO_B]->data); }
inline bool isVFOA() const { return (field[WIREBUS_FLAGS]->data & UBITX_VFOB_FLAG) != UBITX_VFOB_FLAG; }
inline bool isVFOB() const { return (field[WIREBUS_FLAGS]->data & UBITX_VFOB_FLAG) == UBITX_VFOB_FLAG; }
inline bool isSplit() const { return (field[WIREBUS_FLAGS]->data & UBITX_SPLIT_FLAG) == UBITX_SPLIT_FLAG; }
inline bool isRITOn() const { return (field[WIREBUS_FLAGS]->data & UBITX_RIT_FLAG) == UBITX_RIT_FLAG; }
inline bool isXITOn() const { return (field[WIREBUS_FLAGS]->data & UBITX_XIT_FLAG) == UBITX_XIT_FLAG; }
inline bool isCW() const { return (field[WIREBUS_FLAGS]->data & UBITX_CW_FLAG) == UBITX_CW_FLAG; }
inline bool isLSB() const { return (field[WIREBUS_FLAGS]->data & UBITX_USB_FLAG) != UBITX_USB_FLAG; }
inline bool isUSB() const { return (field[WIREBUS_FLAGS]->data & UBITX_USB_FLAG) == UBITX_USB_FLAG; }
static void merge(RigState& a, RigState& b);
BaseField** field;
byte numFields;
byte numDirty;
#ifndef TEENSYDUINO
// These methods are only defined in the Raduino (Arduino) case of the
// RigState, not in the TeensyDSP (Teensy) case.
void writeDirty(); // write fields FROM RigState TO Raduino
void readDirty(); // read variables FROM Raduino TO RigState
#endif
};
#ifndef TEENSYDUINO
extern RigState rigState;
extern UBitxRigState& rigState;
#endif
/*
NOTE: This is all currently OBE, leaving it here for reference/future cleanup.
Protocol discussion:
- I2C master: Raduino
- I2C slave: TeensyDSP
@ -221,5 +364,9 @@ TeensyDSP state:
- Send dirty data over I2C.
- Mark data as clean.
*/
#endif
/***********************************************************************
* EOF
**********************************************************************/

View File

@ -149,13 +149,13 @@ void TS590_FR::handleCommand(const char* cmd) {
if (strlen(cmd) == 3) {
switch (cmd[2]) {
case '0':
rig()->selectVFOA();
rig()->splitOff();
rig()->setVFOA();
rig()->setSplitOff();
break;
case '1':
rig()->selectVFOB();
rig()->splitOff();
rig()->setVFOB();
rig()->setSplitOff();
break;
case '2':
@ -187,9 +187,9 @@ void TS590_FT::handleCommand(const char* cmd) {
switch (cmd[2]) {
case '0':
if (rig()->isVFOA()) {
rig()->splitOff();
rig()->setSplitOff();
} else if (rig()->isVFOB()) {
rig()->splitOn();
rig()->setSplitOn();
} else {
setSyntaxError();
}
@ -197,9 +197,9 @@ void TS590_FT::handleCommand(const char* cmd) {
case '1':
if (rig()->isVFOA()) {
rig()->splitOn();
rig()->setSplitOn();
} else if (rig()->isVFOB()) {
rig()->splitOff();
rig()->setSplitOff();
} else {
setSyntaxError();
}
@ -238,19 +238,19 @@ void TS590_MD::handleCommand(const char* cmd) {
break;
case '1': // LSB
rig()->setModeLSB();
rig()->setLSB();
break;
case '2': // USB
rig()->setModeUSB();
rig()->setUSB();
break;
case '3': // CW
rig()->setModeCW();
rig()->setCW();
break;
case '7': // CW-R
rig()->setModeCWR();
rig()->setCWR();
break;
default:

View File

@ -438,6 +438,7 @@ void i2cRequestEvent(void)
// NEEDS TO GET UPDATED
break;
/*
case I2CMETER_REQCAT:
// Provide latest CAT updates, if any.
//Wire1.write(catState.header); // temporary - just writing a single, null byte
@ -457,7 +458,7 @@ void i2cRequestEvent(void)
Wire1.write(0);
}
break;
*/
default:
break;
}
@ -526,9 +527,9 @@ void loop()
}
// 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 (Rig.isModeCWAny()) {
if (Rig.isModeCWAny()) Keyer.doPaddles();
TR.update(Rig.isModeCWAny(), Keyer.isDown());
//if (TR.transmitting()) return;
}
@ -543,11 +544,11 @@ void loop()
// Update each of the subsystems, beginning with CAT control.
TS590.update();
TR.update(Rig.isCW(), Keyer.isDown());
TR.update(Rig.isModeCWAny(), Keyer.isDown());
Rig.update();
DSP.update();
//if (Rig.isCW()) return;
//if (Rig.isModeCWAny()) return;
#ifdef DEBUG
// For debugging, output some debug info every 1.0" (40 frames @ 40 Hz).
@ -670,7 +671,7 @@ void loop()
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 (Rig.isModeCWAny()) 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) {
// Do stuff that we do once per ADC interval--ADC colllection.
@ -688,7 +689,7 @@ void loop()
//forwardData();
}
//if (Rig.isCW()) return;
//if (Rig.isModeCWAny()) return;
// Check Response Command
if (responseCommand > 0 && sinceForward > LAST_TIME_INTERVAL)