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; return 1;
//Check PTT while auto Sending //Check PTT while auto Sending
autoSendPTTCheck(); //autoSendPTTCheck();
//Check_Cat(3); //Check_Cat(3);
} }
@ -1449,6 +1449,7 @@ void setup()
factory_alignment(); factory_alignment();
#endif #endif
rigState.begin();
} }
//Auto save Frequency and Mode with Protected eeprom life by KD8CEC //Auto save Frequency and Mode with Protected eeprom life by KD8CEC
@ -1473,8 +1474,6 @@ void checkAutoSaveFreqMode()
saveCheckTime = 0; //for reduce cpu use rate saveCheckTime = 0; //for reduce cpu use rate
} }
} }
rigState.begin();
} }
void loop(){ void loop(){

View File

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

View File

@ -994,7 +994,9 @@ char checkCountSMeter = 0;
void idle_process() void idle_process()
{ {
// KC4UPR 2021-02-05 added update process for Raduino-TeensyDSP coordination // KC4UPR 2021-02-05 added update process for Raduino-TeensyDSP coordination
rigState.update(); rigState.send_RIGINF();
delay(1);
rigState.receive_RIGINF();
//updateStateFromRaduino(rigState); //updateStateFromRaduino(rigState);
//doRaduinoToTeensy(&rigState); //doRaduinoToTeensy(&rigState);
//updateRaduinoFromState(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) } //end of while (knob)
if (selectChannel < 20 && selectChannel >= 0) 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; return targetValue;
@ -1290,7 +1290,7 @@ void doMenu(){
default : default :
menuExit(btnState); break; menuExit(btnState); break;
} //end of switch } //end of switch
Check_Cat(0); //To prevent disconnections //Check_Cat(0); //To prevent disconnections
} //end of while } //end of while
//**************************************************************************** //****************************************************************************
@ -1690,7 +1690,7 @@ void menuSetupCarrier(int btn){
si5351bx_setfreq(0, usbCarrier); si5351bx_setfreq(0, usbCarrier);
printCarrierFreq(usbCarrier); printCarrierFreq(usbCarrier);
Check_Cat(0); //To prevent disconnections //Check_Cat(0); //To prevent disconnections
delay(100); delay(100);
} }

Binary file not shown.

View File

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

View File

@ -8,11 +8,13 @@
#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.print("DBG: "); Serial.println(#CMD); CMD; } while (0) #define DBGCMD(CMD) do { Serial.print("DBG: "); Serial.println(#CMD); CMD; } while (0)
#define IFDEBUG(CMD) do { 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)
#define DBGNEWLINE() do {} while (0) #define DBGNEWLINE() do {} while (0)
#define DBGCMD(CMD) do { CMD; } while (0) #define DBGCMD(CMD) do { CMD; } while (0)
#define IFDEBUG(CMD) do {} while (0)
#endif #endif
#endif #endif

View File

@ -15,31 +15,31 @@ class UBitxRig {
inline bool isVFOA() const { return radState.isVFOA(); } inline bool isVFOA() const { return radState.isVFOA(); }
inline bool isVFOB() const { return radState.isVFOB(); } inline bool isVFOB() const { return radState.isVFOB(); }
inline bool isSplit() const { return radState.isSplit(); } inline bool isSplit() const { return radState.isSplit(); }
inline bool isRITOn() const { return radState.isRITOn(); } inline bool isRIT() const { return radState.isRIT(); }
inline bool isXITOn() const { return radState.isXITOn(); } inline bool isXIT() const { return radState.isXIT(); }
inline bool isModeCW() const { return radState.isCW() && radState.isUSB(); } inline bool isModeCWAny() const { return radState.isModeCWAny(); }
inline bool isModeCWR() const { return radState.isCW() && radState.isLSB(); } inline bool isModeCW() const { return radState.isModeCW(); }
inline bool isModeUSB() const { return radState.isUSB() && !radState.isCW(); } inline bool isModeCWR() const { return radState.isModeCWR(); }
inline bool isModeLSB() const { return radState.isLSB() && !radState.isCW(); } inline bool isModeUSB() const { return radState.isModeUSB(); }
inline bool isModeLSB() const { return radState.isModeLSB(); }
inline bool isAI() const { return autoInfo; } inline bool isAI() const { return autoInfo; }
inline void setFreqA(unsigned freq) { catState.setFreqA(freq); } inline void setFreqA(unsigned freq) { catState.setFreqA(freq); }
inline void setFreqB(unsigned freq) { catState.setFreqB(freq); } inline void setFreqB(unsigned freq) { catState.setFreqB(freq); }
inline void setRIT(int freq) { catState.setRIT(freq); } inline void setRIT(int freq) { catState.setRIT(freq); }
inline void setXIT(int freq) { catState.setXIT(freq); } inline void setXIT(int freq) { catState.setXIT(freq); }
inline void selectVFOA() { catState.selectVFOA(); } inline void setVFOA() { catState.setVFOA(); }
inline void selectVFOB() { catState.selectVFOA(); } inline void setVFOB() { catState.setVFOB(); }
inline void toggleVFO() { catState.toggleVFO(); }
inline void setSplitOn() { catState.setSplitOn(); } inline void setSplitOn() { catState.setSplitOn(); }
inline void setSplitOff() { catState.setSplitOff(); } inline void setSplitOff() { catState.setSplitOff(); }
inline void setRITOn() { catState.setRITOn(); } inline void setRITOn() { catState.setRITOn(); }
inline void setRITOff() { catState.setRITOff(); } inline void setRITOff() { catState.setRITOff(); }
inline void setXITOn() { catState.setXITOn(); } inline void setXITOn() { catState.setXITOn(); }
inline void setXITOff() { catState.setXITOff(); } inline void setXITOff() { catState.setXITOff(); }
inline void setModeCW() { catState.setUSB(); catState.setCW(); } inline void setCW() { catState.setCW(); }
inline void setModeCWR() { catState.setLSB(); catState.setCW(); } inline void setCWR() { catState.setCWR(); }
inline void setModeUSB() { catState.setUSB(); catState.setCW(); } inline void setUSB() { catState.setUSB(); }
inline void setModeLSB() { catState.setLSB(); catState.setCW(); } inline void setLSB() { catState.setLSB(); }
inline void aiOn() { autoInfo = true; } inline void aiOn() { autoInfo = true; }
inline void aiOff() { autoInfo = false; } 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
*/
/**********************************************************************/ #include "Debug.h"
// Raduino externs -- generally defined in Raduino.ino or ubitx.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 #ifndef TEENSYDUINO
#include <Wire.h>
#include "ubitx.h"
#include "ubitx_eemap.h" #include "ubitx_eemap.h"
extern unsigned long frequency; extern unsigned long frequency, ritRxFrequency, ritTxFrequency;
extern unsigned long vfoA; extern unsigned long vfoA;
extern unsigned long vfoB; extern unsigned long vfoB;
extern char cwMode; extern char cwMode;
@ -15,48 +64,115 @@ extern char isUSB;
extern char vfoActive; extern char vfoActive;
extern char ritOn; extern char ritOn;
extern char splitOn; extern char splitOn;
extern char inTx;
void setFrequency(unsigned long); void setFrequency(unsigned long);
/*! /*!
* @brief Write dirty fields from the provided rig state, out to the * @brief Send the RigState from the Raduino to the TeensyDSP. The
* Raduino variables. * basic process is: (1) read in any updated (dirty) data
* @param r * from the Raduino's state variables; (2) transmit the dirty
* Reference to a RigState object that will be used to update * data to the TeensyDSP; (2a) for clean data, zeroes are
* the Raduino variables. * transmitted; (3) mark all data as clean.
*/ */
void writeDirty(const RigState& r) { void UBitxRigState::send_RIGINF() {
// VFO A frequency readDirty();
if (r.isDirty(VFOA_WORD)) { Wire.beginTransmission(I2CMETER_ADDR);
if (vfoActive == VFO_A) { Wire.write(I2CMETER_RIGINF);
setFrequency(r.getFreqA()); 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 { } 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 // VFO B frequency
if (r.isDirty(VFOB_WORD)) { if (isDirty(VFOB_WORD)) {
if (vfoActive == VFO_B) { if (vfoActive == VFO_B) {
setFrequency(r.getFreqB()); setFrequency(getFreqB());
} else { } else {
vfoB = r.getFreqB(); vfoB = getFreqB();
} }
} }
// RIT and XIT frequencies // RIT and XIT frequencies
if (r.isDirty(OFFSETS_WORD)) { if (isDirty(OFFSETS_WORD)) {
// RIT // RIT
ritRxFrequency = r.getRIT() + ritTxFrequency; ritRxFrequency = getRIT() + ritTxFrequency;
if ((ritOn == 1) && (inTx == 0)) { if (ritOn == 1) {
setFrequency(ritRxFrequency); if (inTx == 0) {
setFrequency(ritRxFrequency);
} else {
setFrequency(ritTxFrequency);
}
} }
// XIT - TODO // XIT - TODO
} }
// VFO A/B selection // VFO A/B selection
if (r.isDirty(FLAGS_WORD)) { if (isDirty(FLAGS_WORD)) {
char prev = vfoActive; char prev = vfoActive;
vfoActive = r.isVFOA() ? VFO_A : VFO_B; vfoActive = isVFOA() ? VFO_A : VFO_B;
if (vfoActive != prev) { if (vfoActive != prev) {
if (vfoActive == VFO_A) { if (vfoActive == VFO_A) {
if (vfoA != frequency) { if (vfoA != frequency) {
@ -70,11 +186,11 @@ void writeDirty(const RigState& r) {
} }
// Split on/off // Split on/off
splitOn = r.isSplit() ? 1 : 0; splitOn = isSplit() ? 1 : 0;
// RIT on/off // RIT on/off
prev = ritOn; prev = ritOn;
ritOn = r.isRIT() ? 1 : 0; ritOn = isRIT() ? 1 : 0;
if (ritOn != prev) { if (ritOn != prev) {
if ((ritOn == 1) && (inTx == 0)) { if ((ritOn == 1) && (inTx == 0)) {
setFrequency(ritRxFrequency); setFrequency(ritRxFrequency);
@ -86,10 +202,10 @@ void writeDirty(const RigState& r) {
// Mode // Mode
prev = (cwMode << 1) | isUSB; prev = (cwMode << 1) | isUSB;
isUSB = r.isUSB() ? 1 : 0; isUSB = isModeUSB() ? 1 : 0;
if (r.isCW()) { if (isModeCW()) {
cwMode = 2; // 2 = cwu cwMode = 2; // 2 = cwu
} else if (r.isCWR()) { } else if (isModeCWR()) {
cwMode = 1; // 1 = cwl cwMode = 1; // 1 = cwl
} else { } else {
cwMode = 0; // 0 = no cw cwMode = 0; // 0 = no cw
@ -101,274 +217,200 @@ void writeDirty(const RigState& r) {
} }
/*! /*!
* @brief Read current Raduino variables into the provided RigState * @brief Read current Raduino variables into the RigState
* (if they are dirty) and set the appropriate dirty flags. * (if they are changed) and set the appropriate dirty flags.
* @param r * @param r
* RigState reference to put the values into. * RigState reference to put the values into.
*/ */
void readDirty(RigState& r) { void UBitxRigState::readDirty() {
unsigned freq; unsigned long freq;
short offset; short offset;
// VFO A frequency // VFO A frequency
freq = (vfoActive == VFO_A) ? frequency : vfoA; freq = (vfoActive == VFO_A) ? frequency : vfoA;
if (r.getFreqA() != freq) { if (getFreqA() != freq) {
r.setFreqA(freq); setFreqA(freq);
r.setDirty(VFOA_WORD);
} }
// VFO B frequency // VFO B frequency
freq = (vfoActive == VFO_B) ? frequency : vfoB; freq = (vfoActive == VFO_B) ? frequency : vfoB;
if (r.getFreqB() != freq) { if (getFreqB() != freq) {
r.setFreqB(freq); setFreqB(freq);
r.setDirty(VFOB_WORD);
} }
// RIT frequency // RIT frequency
offset = ritRxFrequency - frequency; if (inTx) {
if (r.getRIT() != offset) { offset = ritRxFrequency - ritTxFrequency;
r.setRIT(offset); } else {
r.setDirty(OFFSETS_WORD); offset = frequency - ritTxFrequency;
}
if (getRIT() != offset) {
setRIT(offset);
} }
// XIT frequency // XIT frequency
offset = 0; // xitRxFrequency - frequency; offset = 0; // xitRxFrequency - frequency;
if (r.getXIT() != offset) { if (getXIT() != offset) {
r.setXIT(offset); setXIT(offset);
r.setDirty(OFFSETS_WORD);
} }
bool dirty = false;
// VFO A/B selection // VFO A/B selection
if (r.isVFOA() && vfoActive == VFO_B) { if (isVFOA() && vfoActive == VFO_B) {
r.setVFOB(); setVFOB();
dirty = true; } else if (isVFOB() && vfoActive == VFO_A) {
} else if (r.isVFOB() && vfoActive == VFO_A) { setVFOA();
r.setVFOA();
dirty = true;
} }
// Split selection // Split selection
if (r.isSplit() && splitOn == 0) { if (isSplit() && splitOn == 0) {
r.setSplitOff(); setSplitOff();
dirty = true; } else if (!isSplit() && splitOn != 0) {
} else if (!r.isSplit() && splitOn != 0) { setSplitOn();
r.setSplitOn();
dirty = true;
} }
// RIT selection // RIT selection
if (r.isRIT() && ritOn == 0) { if (isRIT() && ritOn == 0) {
r.setRITOff(); setRITOff();
dirty = true; } else if (!isRIT() && ritOn != 0) {
} else if (!r.isRIT() && ritOn != 0) { setRITOn();
r.setRITOn();
dirty = true;
} }
// XIT selection // XIT selection
r.setXITOff(); //setXITOff();
// TODO // TODO
// Mode // 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; char curr = (cwMode << 1) | isUSB;
if (curr != prev) { if (curr != prev) {
if (cwMode == 2) { if (cwMode == 2) {
r.setCW(); setCW();
} else if (cwMode == 1) { } else if (cwMode == 1) {
r.setCWR(); setCWR();
} else { } else {
if (isUSB) { if (isUSB) {
r.setUSB(); setUSB();
} else { } 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 #endif
/**********************************************************************/ #ifdef DEBUG
BaseField* raduinoFields[WIREBUS_NUM_FIELDS] = { char debugString[81] = {'\0'};
new Field<readNone, writeNone>(),
new Field<readVFOA, writeVFOA>(),
new Field<readVFOB, writeVFOB>(),
new Field<readRIT, writeRIT>(),
new Field<readXIT, writeXIT>(),
new Field<readFlags, writeFlags>(),
};
/**********************************************************************/ void UBitxRigState::serialHexState(const char* label = "RigState") {
Serial.print(label);
RigState::RigState(): RigState(raduinoFields, WIREBUS_NUM_FIELDS) {} 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);
* @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 updateRaduinoState(RigState& r) { void UBitxRigState::serialPrettyState(const char* label = "RigState") {
writeDirty(r); Serial.println(label);
Wire.beginTransmission(I2CMETER_ADDR); sprintf(debugString, "VFO A : %011ld %1c / VFO B : %011ld %1c",
Wire.write(I2CMETER_RIGINF); getFreqA(), isDirty(VFOA_WORD) ? 'D' : ' ', getFreqB(), isDirty(VFOB_WORD) ? 'D' : ' ');
for (RigStateWord i = 0; i < NUM_WORDS; i++) { Serial.println(debugString);
Wire.write((byte*)&r.data, sizeof(r.data)); // - write the field data sprintf(debugString, "RIT : %011ld %1c / XIT : %011ld %1c",
r.setClean(i); getRIT(), isDirty(OFFSETS_WORD) ? 'D' : ' ', getXIT(), isDirty(OFFSETS_WORD) ? 'D' : ' ');
} Serial.println(debugString);
Wire.endTransmission(); sprintf(debugString, "Split? %1c / VFO? %1c / RIT? %1c / XIT? %1c / Mode? %3s",
isSplit() ? 'Y' : 'N', isVFOA() ? 'A' : 'B', isRIT() ? 'Y' : 'N', isXIT() ? 'Y' : 'N',
delay(1); // 1ms - some delay required between ending transmission and requesting? isModeUSB() ? "USB" : (isModeLSB() ? "LSB" : (isModeCW() ? "CW " : (isModeCWR() ? "CWR" : " "))));
Serial.println(debugString);
// 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--;
}
}
} }
/**********************************************************************/ #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
* 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;
}
}
}
}
/**********************************************************************/
/*!
* @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 #ifndef TEENSYDUINO
RigState rigState; UBitxRigState _rigState;
UBitxRigState& rigState = _rigState;
#endif #endif
/********************************************************************** /***********************************************************************
* EOF * * EOF
**********************************************************************/ **********************************************************************/

View File

@ -1,3 +1,7 @@
/*!
* @file RigState.h
*/
#ifndef __RigState_h__ #ifndef __RigState_h__
#define __RigState_h__ #define __RigState_h__
@ -11,6 +15,12 @@
#define UBITX_USB_FLAG 0x00000020 #define UBITX_USB_FLAG 0x00000020
#define UBITX_TX_FLAG 0x00000040 #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 { enum RigStateWord {
DIRTY_WORD = 0, DIRTY_WORD = 0,
VFOA_WORD, VFOA_WORD,
@ -20,174 +30,307 @@ enum RigStateWord {
NUM_WORDS 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 { 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) { 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) { 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) { 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]; } * @brief Set the VFO A frequency.
inline void getFreqB(uint32_r freq) { data[VFOB_WORD] = freq; } *
inline uint32_t getFreqB() const { return data[VFOB_WORD]; } * @param freq
inline void setRIT(int16_t offset) { data[OFFSETS_WORD] = (offset << 16) | (0x0000FFFF & data[OFFSETS_WORD]); } * The new frequency in Hz.
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 void setFreqA(uint32_t freq, bool mark = true) {
inline int16_t getXIT() const { return 0x0000FFFF & data[OFFSETS_WORD]; } DISABLEINTS( data[VFOA_WORD] = freq;
inline void setVFOA() { data[FLAGS_WORD] &= ~UBITX_VFOB_FLAG; } if (mark) setDirty(VFOA_WORD) );
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 uint32_t getFreqA() const {
inline void setSplitOn() { data[FLAGS_WORD] |= UBITX_SPLIT_FLAG; } uint32_t result;
inline void setSplitOff() { data[FLAGS_WORD] &= ~UBITX_SPLIT_FLAG; } DISABLEINTS( result = data[VFOA_WORD] );
inline bool isSplit() const { data[FLAGS_WORD] & UBITX_SPLIT_FLAG ? true : false; } return result;
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); }
};
#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 #endif
/**********************************************************************/ #ifndef TEENSYDUINO
// NEW IMPLEMENTATION // These methods are only defined in the Raduino (Arduino) case of the
// RigState, not in the TeensyDSP (Teensy) case.
struct BaseField { void writeDirty(); // write fields FROM RigState TO Raduino
BaseField(): dirty(false), data(0) {} void readDirty(); // read variables FROM Raduino TO RigState
virtual ~BaseField() = 0; #endif
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 #ifndef TEENSYDUINO
extern RigState rigState; extern UBitxRigState& rigState;
#endif #endif
/* /*
NOTE: This is all currently OBE, leaving it here for reference/future cleanup.
Protocol discussion: Protocol discussion:
- I2C master: Raduino - I2C master: Raduino
- I2C slave: TeensyDSP - I2C slave: TeensyDSP
@ -221,5 +364,9 @@ TeensyDSP state:
- Send dirty data over I2C. - Send dirty data over I2C.
- Mark data as clean. - Mark data as clean.
*/ */
#endif #endif
/***********************************************************************
* EOF
**********************************************************************/

View File

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

View File

@ -438,6 +438,7 @@ void i2cRequestEvent(void)
// NEEDS TO GET UPDATED // NEEDS TO GET UPDATED
break; break;
/*
case I2CMETER_REQCAT: case I2CMETER_REQCAT:
// Provide latest CAT updates, if any. // Provide latest CAT updates, if any.
//Wire1.write(catState.header); // temporary - just writing a single, null byte //Wire1.write(catState.header); // temporary - just writing a single, null byte
@ -457,7 +458,7 @@ void i2cRequestEvent(void)
Wire1.write(0); Wire1.write(0);
} }
break; break;
*/
default: default:
break; break;
} }
@ -526,9 +527,9 @@ void loop()
} }
// If CW mode, we need to update keying a lot... // If CW mode, we need to update keying a lot...
if (Rig.isCW()) { if (Rig.isModeCWAny()) {
if (Rig.isCW()) Keyer.doPaddles(); if (Rig.isModeCWAny()) Keyer.doPaddles();
TR.update(Rig.isCW(), Keyer.isDown()); TR.update(Rig.isModeCWAny(), Keyer.isDown());
//if (TR.transmitting()) return; //if (TR.transmitting()) return;
} }
@ -543,11 +544,11 @@ void loop()
// Update each of the subsystems, beginning with CAT control. // Update each of the subsystems, beginning with CAT control.
TS590.update(); TS590.update();
TR.update(Rig.isCW(), Keyer.isDown()); TR.update(Rig.isModeCWAny(), Keyer.isDown());
Rig.update(); Rig.update();
DSP.update(); DSP.update();
//if (Rig.isCW()) return; //if (Rig.isModeCWAny()) 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).
@ -670,7 +671,7 @@ 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 (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) { 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.
@ -688,7 +689,7 @@ void loop()
//forwardData(); //forwardData();
} }
//if (Rig.isCW()) return; //if (Rig.isModeCWAny()) return;
// Check Response Command // Check Response Command
if (responseCommand > 0 && sinceForward > LAST_TIME_INTERVAL) if (responseCommand > 0 && sinceForward > LAST_TIME_INTERVAL)