Long way from being compilable on either the Raduino or the TeensyDSP. Lot of changes in progress.

This commit is contained in:
Rob French 2021-02-14 23:04:29 -06:00
parent e5de516633
commit 8a416608a1
5 changed files with 489 additions and 697 deletions

View File

@ -13,116 +13,48 @@ class UBitxRig {
public: public:
inline void begin() {} inline void begin() {}
inline void update() {} inline void update() {}
inline unsigned long getFreqA() const { return state.vfo[0]; } inline unsigned getFreqA() const { return catState.getFreqA(); }
inline unsigned long getFreqB() const { return state.vfo[1]; } inline unsigned getFreqB() const { return catState.getFreqB(); }
inline long getRIT() const { return state.rit; } inline int getRIT() const { return catState.getRIT(); }
inline long getXIT() const { return state.xit; } inline int getXIT() const { return catState.getXIT(); }
inline bool isVFOA() const { return (state.flags & UBITX_VFOB_FLAG) != UBITX_VFOB_FLAG; } inline bool isVFOA() const { return catState.isVFOA(); }
inline bool isVFOB() const { return (state.flags & UBITX_VFOB_FLAG) == UBITX_VFOB_FLAG; } inline bool isVFOB() const { return catState.isVFOB(); }
inline bool isSplit() const { return (state.flags & UBITX_SPLIT_FLAG) == UBITX_SPLIT_FLAG; } inline bool isSplit() const { return catState.isSplit(); }
inline bool isRITOn() const { return (state.flags & UBITX_RIT_FLAG) == UBITX_RIT_FLAG; } inline bool isRITOn() const { return catState.isRITOn(); }
inline bool isXITOn() const { return (state.flags & UBITX_XIT_FLAG) == UBITX_XIT_FLAG; } inline bool isXITOn() const { return catState.isXITOn(); }
inline bool isCW() const { return (state.flags & UBITX_CW_FLAG) == UBITX_CW_FLAG; } inline bool isModeCW() const { return catState.isCW() && catState.isUSB(); }
inline bool isLSB() const { return (state.flags & UBITX_USB_FLAG) != UBITX_USB_FLAG; } inline bool isModeCWR() const { return catState.isCW() && catState.isLSB(); }
inline bool isUSB() const { return (state.flags & UBITX_USB_FLAG) == UBITX_USB_FLAG; } inline bool isModeUSB() const { return catState.isUSB() && !catState.isCW(); }
inline bool getAI() const { return autoInfo; } inline bool isModeLSB() const { return catState.isLSB() && !catState.isCW(); }
inline bool updatedByCAT() const { return lastUpdatedBy == CATSource; } inline bool isAI() const { return autoInfo; }
inline bool updatedByRaduino() const { return lastUpdatedBy == RaduinoSource; } //inline bool updatedByCAT() const { return lastUpdatedBy == CATSource; }
//inline bool updatedByRaduino() const { return lastUpdatedBy == RaduinoSource; }
inline void clearUpdate() { lastUpdatedBy = NoSource; } //inline void clearUpdate() { lastUpdatedBy = NoSource; }
inline void setRaduinoUpdate() { lastUpdatedBy = RaduinoSource; } //inline void setRaduinoUpdate() { lastUpdatedBy = RaduinoSource; }
inline void setCATUpdate() { lastUpdatedBy = CATSource; } //inline void setCATUpdate() { lastUpdatedBy = CATSource; }
inline void setFreqA(unsigned long freq, bool isCAT = false) { inline void setFreqA(unsigned freq) { catState.setFreqA(freq); }
lastUpdatedBy = isCAT ? CATSource : RaduinoSource; inline void setFreqB(unsigned freq) { catState.setFreqB(freq); }
state.vfo[0] = freq; inline void setRIT(int freq) { catState.setRIT(freq); }
} inline void setXIT(int freq) { catState.setXIT(freq); }
inline void selectVFOA() { catState.selectVFOA(); }
inline void setFreqB(unsigned long freq, bool isCAT = false) { inline void selectVFOB() { catState.selectVFOA(); }
lastUpdatedBy = isCAT ? CATSource : RaduinoSource; inline void toggleVFO() { catState.toggleVFO(); }
state.vfo[1] = freq; inline void setSplitOn() { catState.setSplitOn(); }
} inline void setSplitOff() { catState.setSplitOff(); }
inline void setRITOn() { catState.setRITOn(); }
inline void setRIT(short offset, bool isCAT = false) { inline void setRITOff() { catState.setRITOff(); }
lastUpdatedBy = isCAT ? CATSource : RaduinoSource; inline void setXITOn() { catState.setXITOn(); }
state.rit = offset; inline void setXITOff() { catState.setXITOff(); }
} inline void setModeCW() { catState.setUSB(); catState.setCW(); }
inline void setModeCWR() { catState.setLSB(); catState.setCW(); }
inline void setXIT(short offset, bool isCAT = false) { inline void setModeUSB() { catState.setUSB(); catState.setCW(); }
lastUpdatedBy = isCAT ? CATSource : RaduinoSource; inline void setModeLSB() { catState.setLSB(); catState.setCW(); }
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 aiOn() { autoInfo = true; }
inline void aiOff() { autoInfo = false; } inline void aiOff() { autoInfo = false; }
uint8_t* const stateAsBytes() const { return (uint8_t* const)&state; }
inline void updateState(UBitxRigState& r, bool isCAT = false) { inline void updateState(UBitxRigState& r, bool isCAT = false) {
if ((r.vfo[0] == state.vfo[0]) && if ((r.vfo[0] == state.vfo[0]) &&
(r.vfo[1] == state.vfo[1]) && (r.vfo[1] == state.vfo[1]) &&
@ -150,7 +82,8 @@ class UBitxRig {
private: private:
bool autoInfo = false; bool autoInfo = false;
UpdateSource lastUpdatedBy = NoSource; UpdateSource lastUpdatedBy = NoSource;
UBitxRigState state; UBitxRigState catState;
UBitxRigState radState;
}; };
extern UBitxRig Rig; extern UBitxRig Rig;

View File

@ -1,455 +1,370 @@
#include "RigState.h" #include ""
/**********************************************************************/ /**********************************************************************/
// Handle the case of the TeensyDSP. // Raduino externs -- generally defined in Raduino.ino or ubitx.h
#ifdef TEENSYDUINO #ifndef TEENSYDUINO
/**********************************************************************/ extern unsigned long frequency;
extern unsigned long vfoA;
bool readVFOA(uint32_t* d) { extern unsigned long vfoB;
unsigned freq = (vfoActive == VFO_A) ? frequency : vfoA; extern char cwMode;
if (*d == freq) { extern char isUSB;
return false extern char vfoActive;
} else { extern char ritOn;
*d = freq; extern char splitOn;
return true; void setFrequency(unsigned long);
}
}
void writeVFOA(uint32_t d) {
if (vfoActive == VFO_A) {
setFrequency(d);
} else {
vfoA = frequency;
}
}
bool readVFOB(uint32_t* d) {
unsigned freq = (vfoActive == VFO_B) ? frequency : vfoB;
if (*d == freq) {
return false
} else {
*d = freq;
return true;
}
}
void writeVFOB(uint32_t d) {
if (vfoActive == VFO_B) {
setFrequency(d);
} else {
vfoB = frequency;
}
}
bool readRIT(uint32_t* d) {
int freq = ritRxFrequency - frequency;
if (*d == (uint32_t)freq) {
return false;
} else {
*d = (uint32_t)freq;
return true;
}
}
void writeRIT(uint32_t d) {
ritRxFrequency = (int)d + ritTxFrequency;
if ((ritOn == 1) && (inTx == 0)) {
setFrequency(ritRxFrequency);
}
}
bool readXIT(uint32_t* d) {
return false;
}
void writeXIT(uint32_t d) {
}
bool readFlags(uint32_t* d) {
uint32_t flags = 0
flags = 0;
flags |= (vfoActive == VFO_B ? UBITX_VFOB_FLAG : 0);
flags |= (cwMode != 0 ? UBITX_CW_FLAG : 0);
flags |= (isUSB != 0 ? UBITX_USB_FLAG : 0);
flags |= (splitOn != 0 ? UBITX_SPLIT_FLAG : 0);
flags |= (ritOn != 0 ? UBITX_RIT_FLAG : 0);
//flags |= (xitOn != 0 ? UBITX_XIT_FLAG : 0);
if (*d == flags) {
return false;
} else {
*d = flags;
return true;
}
}
void writeFlags(uint32_t d) {
char prev = vfoActive;
vfoActive = (d & UBITX_VFOB_FLAG ? VFO_B : VFO_A);
if (vfoActive != prev) {
if (vfoActive == VFO_A) {
if (vfoA != frequency) {
setFrequency(vfoA);
}
} else if (vfoActive == VFO_B) {
if (vfoB != frequency) {
setFrequency(vfoB);
}
}
}
splitOn = rigState.flags & UBITX_SPLIT_FLAG ? 1 : 0;
prev = ritOn;
ritOn = rigState.flags & UBITX_RIT_FLAG ? 1 : 0;
if (ritOn != prev) {
if ((ritOn == 1) && (inTx == 0)) {
setFrequency(ritRxFrequency);
}
}
char prev = (cwMode << 1) | isUSB;
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;
}
if ((cwMode << 1) | isUSB != prev) {
setFrequency(frequency);
}
}
/**********************************************************************/
RigState inState;
RigState outState;
void RigState::begin() {
field[WIREBUS_VFO_A].data = vfoA;
field[WIREBUS_VFO_B].data = vfoB;
field[WIREBUS_RIT_OFS].data = (uint32_t)(ritRxFrequency - frequency);
field[WIREBUS_XIT_OFS].data = 0;
field[WIREBUS_FLAGS].data = 0;
field[WIREBUS_FLAGS].data |= (vfoActive == VFO_B ? UBITX_VFOB_FLAG : 0);
field[WIREBUS_FLAGS].data |= (cwMode != 0 ? UBITX_CW_FLAG : 0);
field[WIREBUS_FLAGS].data |= (isUSB != 0 ? UBITX_USB_FLAG : 0);
field[WIREBUS_FLAGS].data |= (splitOn != 0 ? UBITX_SPLIT_FLAG : 0);
field[WIREBUS_FLAGS].data |= (ritOn != 0 ? UBITX_RIT_FLAG : 0);
//field[WIREBUS_FLAGS].data |= (xitOn != 0 ? UBITX_XIT_FLAG : 0);
for (byte i = 0; i < WIREBUS_NUM_FIELDS; i++) {
field[i].dirty = true; // Set true to force an initial send to the TeensyDSP.
}
readFunc[WIREBUS_VFO_A] = &readVFOA;
readFunc[WIREBUS_VFO_B] = &readVFOB;
readFunc[WIREBUS_RIT_OFS] = &readRIT;
readFunc[WIREBUS_XIT_OFS] = &readXIT;
readFunc[WIREBUS_FLAGS] = &readFlags;
writeFunc[WIREBUS_VFO_A] = &writeVFOA;
writeFunc[WIREBUS_VFO_B] = &writeVFOB;
writeFunc[WIREBUS_RIT_OFS] = &writeRIT;
writeFunc[WIREBUS_XIT_OFS] = &writeXIT;
writeFunc[WIREBUS_FLAGS] = &writeFlags;
}
void RigState::update() {
// First we need to determine which fields have changed (and are
// thus dirty and need to be sent to the TeensyDSP).
for (byte i = 0; i < WIREBUS_NUM_FIELDS; i++) {
if (read(i)) {
field[i].dirty = true;
numDirty++;
}
}
// Next we need to send the current (changed) Raduino information
// to the TeensyDSP. The expected response is the number of fields
// (in bytes) that the TeensyDSP needs to send in response.
Wire.beginTransmission(I2CMETER_ADDR);
Wire.write(I2CMETER_RIGINF);
Wire.write(numDirty * sizeof(Field), 1); // Write the number of dirty fields (in bytes).
for (int i = 0; i < WIREBUS_NUM_FIELDS; i++) {
if (field[i].dirty) { // Write each field that is dirty to the bus.
Wire.write((byte*)(&(field[i].data)), sizeof(Field));
field[i].dirty = false;
numDirty--;
}
}
Wire.endTransmission();
// Now we're going to read the response from the TeensyDSP. All
// fields should be marked as clean at this point (unless there's
// something that has been updated via interrupt???).
Wire.requestFrom(I2CMETER_ADDR, 1);
byte numBytes;
while (Wire.available()) {
numBytes = Wire.read(); // Should only get executed for one byte... but just in case.
}
if (numBytes == 0) return;
// Let the TeensyDSP know that we want it to send its deltas now.
Wire.beginTransmission(I2CMETER_ADDR);
Wire.write(I2CMETER_RIGREQ);
Wire.endTransmission();
// Retrieve all of the deltas. Mark any received field as dirty.
Wire.requestFrom(I2CMETER_ADDR, numBytes);
int index = -1;
byte* ptr;
while (Wire.available()) {
byte b = Wire.read();
if (index = -1) {
ptr = (byte*)(&(field[b].data));
field[b].dirty = true;
numDirty++;
index = 0;
} else {
ptr[index++] = b;
if (index == 4) {
index = -1;
}
}
}
// Perform the corresponding update for each dirty field.
for (byte i = 0; i < WIREBUS_NUM_FIELDS; i++) {
if (field[i].dirty) {
write(i);
field[i].dirty = false;
numDirty--;
}
}
}
/**********************************************************************/
// Handle the case of the Raduino
#else
/**********************************************************************/
bool readVFOA(uint32_t* d) {
unsigned freq = (vfoActive == VFO_A) ? frequency : vfoA;
if (*d == freq) {
return false
} else {
*d = freq;
return true;
}
}
void writeVFOA(uint32_t d) {
if (vfoActive == VFO_A) {
setFrequency(d);
} else {
vfoA = frequency;
}
}
bool readVFOB(uint32_t* d) {
unsigned freq = (vfoActive == VFO_B) ? frequency : vfoB;
if (*d == freq) {
return false
} else {
*d = freq;
return true;
}
}
void writeVFOB(uint32_t d) {
if (vfoActive == VFO_B) {
setFrequency(d);
} else {
vfoB = frequency;
}
}
bool readRIT(uint32_t* d) {
int freq = ritRxFrequency - frequency;
if (*d == (uint32_t)freq) {
return false;
} else {
*d = (uint32_t)freq;
return true;
}
}
void writeRIT(uint32_t d) {
ritRxFrequency = (int)d + ritTxFrequency;
if ((ritOn == 1) && (inTx == 0)) {
setFrequency(ritRxFrequency);
}
}
bool readXIT(uint32_t* d) {
return false;
}
void writeXIT(uint32_t d) {
}
bool readFlags(uint32_t* d) {
uint32_t flags = 0
flags = 0;
flags |= (vfoActive == VFO_B ? UBITX_VFOB_FLAG : 0);
flags |= (cwMode != 0 ? UBITX_CW_FLAG : 0);
flags |= (isUSB != 0 ? UBITX_USB_FLAG : 0);
flags |= (splitOn != 0 ? UBITX_SPLIT_FLAG : 0);
flags |= (ritOn != 0 ? UBITX_RIT_FLAG : 0);
//flags |= (xitOn != 0 ? UBITX_XIT_FLAG : 0);
if (*d == flags) {
return false;
} else {
*d = flags;
return true;
}
}
void writeFlags(uint32_t d) {
char prev = vfoActive;
vfoActive = (d & UBITX_VFOB_FLAG ? VFO_B : VFO_A);
if (vfoActive != prev) {
if (vfoActive == VFO_A) {
if (vfoA != frequency) {
setFrequency(vfoA);
}
} else if (vfoActive == VFO_B) {
if (vfoB != frequency) {
setFrequency(vfoB);
}
}
}
splitOn = rigState.flags & UBITX_SPLIT_FLAG ? 1 : 0;
prev = ritOn;
ritOn = rigState.flags & UBITX_RIT_FLAG ? 1 : 0;
if (ritOn != prev) {
if ((ritOn == 1) && (inTx == 0)) {
setFrequency(ritRxFrequency);
}
}
char prev = (cwMode << 1) | isUSB;
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;
}
if ((cwMode << 1) | isUSB != prev) {
setFrequency(frequency);
}
}
/**********************************************************************/
RigState rigState;
void RigState::begin() {
field[WIREBUS_VFO_A].data = vfoA;
field[WIREBUS_VFO_B].data = vfoB;
field[WIREBUS_RIT_OFS].data = (uint32_t)(ritRxFrequency - frequency);
field[WIREBUS_XIT_OFS].data = 0;
field[WIREBUS_FLAGS].data = 0;
field[WIREBUS_FLAGS].data |= (vfoActive == VFO_B ? UBITX_VFOB_FLAG : 0);
field[WIREBUS_FLAGS].data |= (cwMode != 0 ? UBITX_CW_FLAG : 0);
field[WIREBUS_FLAGS].data |= (isUSB != 0 ? UBITX_USB_FLAG : 0);
field[WIREBUS_FLAGS].data |= (splitOn != 0 ? UBITX_SPLIT_FLAG : 0);
field[WIREBUS_FLAGS].data |= (ritOn != 0 ? UBITX_RIT_FLAG : 0);
//field[WIREBUS_FLAGS].data |= (xitOn != 0 ? UBITX_XIT_FLAG : 0);
for (byte i = 0; i < WIREBUS_NUM_FIELDS; i++) {
field[i].dirty = true; // Set true to force an initial send to the TeensyDSP.
}
readFunc[WIREBUS_VFO_A] = &readVFOA;
readFunc[WIREBUS_VFO_B] = &readVFOB;
readFunc[WIREBUS_RIT_OFS] = &readRIT;
readFunc[WIREBUS_XIT_OFS] = &readXIT;
readFunc[WIREBUS_FLAGS] = &readFlags;
writeFunc[WIREBUS_VFO_A] = &writeVFOA;
writeFunc[WIREBUS_VFO_B] = &writeVFOB;
writeFunc[WIREBUS_RIT_OFS] = &writeRIT;
writeFunc[WIREBUS_XIT_OFS] = &writeXIT;
writeFunc[WIREBUS_FLAGS] = &writeFlags;
}
void RigState::update() {
// First we need to determine which fields have changed (and are
// thus dirty and need to be sent to the TeensyDSP).
for (byte i = 0; i < WIREBUS_NUM_FIELDS; i++) {
if (read(i)) {
field[i].dirty = true;
numDirty++;
}
}
// Next we need to send the current (changed) Raduino information
// to the TeensyDSP. The expected response is the number of fields
// (in bytes) that the TeensyDSP needs to send in response.
Wire.beginTransmission(I2CMETER_ADDR);
Wire.write(I2CMETER_RIGINF);
Wire.write(numDirty * sizeof(Field), 1); // Write the number of dirty fields (in bytes).
for (int i = 0; i < WIREBUS_NUM_FIELDS; i++) {
if (field[i].dirty) { // Write each field that is dirty to the bus.
Wire.write((byte*)(&(field[i].data)), sizeof(Field));
field[i].dirty = false;
numDirty--;
}
}
Wire.endTransmission();
// Now we're going to read the response from the TeensyDSP. All
// fields should be marked as clean at this point (unless there's
// something that has been updated via interrupt???).
Wire.requestFrom(I2CMETER_ADDR, 1);
byte numBytes;
while (Wire.available()) {
numBytes = Wire.read(); // Should only get executed for one byte... but just in case.
}
if (numBytes == 0) return;
// Let the TeensyDSP know that we want it to send its deltas now.
Wire.beginTransmission(I2CMETER_ADDR);
Wire.write(I2CMETER_RIGREQ);
Wire.endTransmission();
// Retrieve all of the deltas. Mark any received field as dirty.
Wire.requestFrom(I2CMETER_ADDR, numBytes);
int index = -1;
byte* ptr;
while (Wire.available()) {
byte b = Wire.read();
if (index = -1) {
ptr = (byte*)(&(field[b].data));
field[b].dirty = true;
numDirty++;
index = 0;
} else {
ptr[index++] = b;
if (index == 4) {
index = -1;
}
}
}
// Perform the corresponding update for each dirty field.
for (byte i = 0; i < WIREBUS_NUM_FIELDS; i++) {
if (field[i].dirty) {
write(i);
field[i].dirty = false;
numDirty--;
}
}
}
#endif #endif
/**********************************************************************/
// Raduino functors - used to read/write from Raduino state
#ifndef TEENSYDUINO
struct readNone {
bool operator()(uint32_t* d) {
return false;
}
}
struct writeNone {
void operator()(uint32_t d) {
}
}
struct readVFOA {
bool operator()(uint32_t* d) {
unsigned freq = (vfoActive == VFO_A) ? frequency : vfoA;
if (*d == freq) {
return false;
} else {
*d = freq;
return true;
}
}
};
struct writeVFOA {
void operator()(uint32_t d) {
if (vfoActive == VFO_A) {
setFrequency(d);
} else {
vfoA = frequency;
}
}
};
struct readVFOB {
bool operator()(uint32_t* d) {
unsigned freq = (vfoActive == VFO_B) ? frequency : vfoB;
if (*d == freq) {
return false
} else {
*d = freq;
return true;
}
}
};
struct writeVFOB {
void operator()(uint32_t d) {
if (vfoActive == VFO_B) {
setFrequency(d);
} else {
vfoB = frequency;
}
}
};
struct readRIT {
bool operator()(uint32_t* d) {
int freq = ritRxFrequency - frequency;
if (*d == (uint32_t)freq) {
return false;
} else {
*d = (uint32_t)freq;
return true;
}
}
};
struct writeRIT {
void operator()(uint32_t d) {
ritRxFrequency = (int)d + ritTxFrequency;
if ((ritOn == 1) && (inTx == 0)) {
setFrequency(ritRxFrequency);
}
}
};
struct readXIT {
bool operator()(uint32_t* d) {
return false;
}
};
struct writeXIT {
void operator()(uint32_t d) {
}
};
struct readFlags {
bool operator()(uint32_t* d) {
uint32_t flags = 0
flags = 0;
flags |= (vfoActive == VFO_B ? UBITX_VFOB_FLAG : 0);
flags |= (cwMode != 0 ? UBITX_CW_FLAG : 0);
flags |= (isUSB != 0 ? UBITX_USB_FLAG : 0);
flags |= (splitOn != 0 ? UBITX_SPLIT_FLAG : 0);
flags |= (ritOn != 0 ? UBITX_RIT_FLAG : 0);
//flags |= (xitOn != 0 ? UBITX_XIT_FLAG : 0);
if (*d == flags) {
return false;
} else {
*d = flags;
return true;
}
}
};
struct writeFlags {
void operator()(uint32_t d) {
char prev = vfoActive;
vfoActive = (d & UBITX_VFOB_FLAG ? VFO_B : VFO_A);
if (vfoActive != prev) {
if (vfoActive == VFO_A) {
if (vfoA != frequency) {
setFrequency(vfoA);
}
} else if (vfoActive == VFO_B) {
if (vfoB != frequency) {
setFrequency(vfoB);
}
}
}
splitOn = d & UBITX_SPLIT_FLAG ? 1 : 0;
prev = ritOn;
ritOn = d & UBITX_RIT_FLAG ? 1 : 0;
if (ritOn != prev) {
if ((ritOn == 1) && (inTx == 0)) {
setFrequency(ritRxFrequency);
}
}
char prev = (cwMode << 1) | isUSB;
isUSB = d.flags & UBITX_USB_FLAG ? 1 : 0;
if (d.flags & UBITX_CW_FLAG) {
cwMode = isUSB ? 2 : 1; // 2 = cwu / 1 = cwl
} else {
cwMode = 0;
}
if ((cwMode << 1) | isUSB != prev) {
setFrequency(frequency);
}
}
};
#endif
/**********************************************************************/
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>(),
};
/**********************************************************************/
RaduinoState::RaduinoState(): RigState(raduinoFields, WIREBUS_NUM_FIELDS) {}
void RaduinoState::begin() {
for (byte i = 0; i < numFields; i++) {
if (read(i)) {
makeDirty(i);
}
}
}
void RaduinoState::update() {
// First we need to determine which fields have changed (and are
// thus dirty and need to be sent to the TeensyDSP).
for (byte i = 0; i < numFields; i++) {
if (read(i)) {
makeDirty(i);
}
}
// Next we need to send the current (changed) Raduino information
// to the TeensyDSP. The expected response is the number of fields
// (in bytes) that the TeensyDSP needs to send in response.
Wire.beginTransmission(I2CMETER_ADDR);
Wire.write(I2CMETER_RIGINF);
// NOTE - I don't think I actually need to do this line, i.e. I don't think the slave cares... it'll read what is sent to it.
//Wire.write(numDirty * (sizeof(byte) + sizeof(uint32_t)), 1); // Write the number of dirty fields (in bytes).
for (byte i = 0; i < numFields; i++) {
if (isDirty(i)) { // Write each field that is dirty to the bus.
Wire.write(i); // write the field number/ID
Wire.write(data(i), dataSize(i)); // write the field data
makeClean(i);
}
}
Wire.endTransmission();
// Now we're going to read the response from the TeensyDSP. All
// fields should be marked as clean at this point (unless there's
// something that has been updated via interrupt???).
Wire.requestFrom(I2CMETER_ADDR, 1);
byte numBytes;
while (Wire.available()) {
numBytes = Wire.read(); // Should only get executed for one byte... but just in case.
}
if (numBytes == 0) return;
// Let the TeensyDSP know that we want it to send its deltas now.
Wire.beginTransmission(I2CMETER_ADDR);
Wire.write(I2CMETER_RIGREQ);
Wire.endTransmission();
// 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--;
}
}
}
/**********************************************************************/
/*!
* @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 RaduinoState::receiveRIGINF() {
// 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 RaduinoState::respondRIGINF(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;
#endif
/********************************************************************** /**********************************************************************
* EOF * * EOF *

View File

@ -28,42 +28,37 @@ struct UBitxRigState {
/**********************************************************************/ /**********************************************************************/
// NEW IMPLEMENTATION // NEW IMPLEMENTATION
struct Field { struct BaseField {
BaseField(): dirty(false), data(0) {}
virtual ~BaseField() = 0;
bool dirty; bool dirty;
uint32_t data; uint32_t data;
/* virtual bool read() = 0;
template<typename STREAM> void writeChanges() { virtual void write() const = 0;
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& f) {
if (dirty) {
f.data = data;
f.dirty = true;
} else if (f.dirty) {
data = f.data;
dirty = true;
}
}
inline void markClean() { dirty = false; }
}; };
#define WIREBUS_NONE 0 template<typename R, typename W>
struct Field : public BaesField {
/*!
* @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_NULL 0 // an empty field
#define WIREBUS_VFO_A 1 #define WIREBUS_VFO_A 1
#define WIREBUS_VFO_B 2 #define WIREBUS_VFO_B 2
#define WIREBUS_RIT_OFS 3 #define WIREBUS_RIT_OFS 3
@ -71,15 +66,9 @@ struct Field {
#define WIREBUS_FLAGS 5 #define WIREBUS_FLAGS 5
#define WIREBUS_NUM_FIELDS 6 #define WIREBUS_NUM_FIELDS 6
typedef bool (*readfunc)(uint32_t*); class RigState {
typedef void (*writefunc)(uint32_t); public:
RigState(BaseField** f = NULL, int numf = 0): field(f), numFields(numf), numDirty(0) {}
struct RigState {
Field field[WIREBUS_NUM_FIELDS];
readfunc readFunc[WIREBUS_NUM_FIELDS];
writefunc writeFunc[WIREBUS_NUM_FIELDS;
int numDirty;
void begin(); void begin();
void update(); void update();
@ -88,7 +77,7 @@ struct RigState {
* it to update the rig state. * it to update the rig state.
*/ */
inline bool read(byte i) { inline bool read(byte i) {
return readFunc[i](&field[i].data); return field[i]->read();
} }
/*! /*!
@ -96,95 +85,56 @@ struct RigState {
* external value. * external value.
*/ */
inline void write(byte i) { inline void write(byte i) {
writeFunc[i](field[i].data); field[i]->write();
} }
inline unsigned getFreqA() const { return field[WIREBUS_VFO_A].data; } inlie bool isDirty(byte i) {
inline unsigned getFreqB() const { return field[WIREBUS_VFO_B].data; } return field[i]->dirty();
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; }
/*
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() { inline void makeDirty(byte i) {
vfoA.writeChanges<STREAM>(); if (!field[i]->dirty) {
vfoB.writeChanges<STREAM>(); field[i]->dirty = true;
rit.writeChanges<STREAM>(); numDirty++;
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) { inline void makeClean(byte i) {
vfoA.merge(r.vfoA); if (field[i]->dirty) {
vfoB.merge(r.vfoB); field[i]->dirty = false;
rit.merge(r.rit); numDirty--;
xit.merge(r.xit); }
flags.merge(r.flags); }
inline byte* data(byte i) {
return (byte*)(&(field[i]->data));
} }
inline void markClean(RigState& r) { inline int dataSize(byte i) {
vfoA.markClean(); return sizeof(field[i]->data);
vfoB.markClean();
rit.markClean();
xit.markClean();
flags.markClean();
} }
*/
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;
}; };
#ifdef TEENSYDUINO #ifndef TEENSYDUINO
extern RigState inState; // the state as received from the Raduino
extern RigState outState; // the state as commanded via CAT
#else
extern RigState rigState; extern RigState rigState;

View File

@ -77,7 +77,7 @@ void TS590Command::process(const char* cmd) {
DBGCMD( handleCommand(cmd) ); DBGCMD( handleCommand(cmd) );
switch(theError) { switch(theError) {
case NoError: case NoError:
if (theRig->getAI()) { if (theRig->isAI()) {
DBGCMD( sendResponse(cmd) ); DBGCMD( sendResponse(cmd) );
} }
break; break;
@ -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(true); rig()->selectVFOA();
rig()->splitOff(true); rig()->splitOff();
break; break;
case '1': case '1':
rig()->selectVFOB(true); rig()->selectVFOB();
rig()->splitOff(true); rig()->splitOff();
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(true); rig()->splitOff();
} else if (rig()->isVFOB()) { } else if (rig()->isVFOB()) {
rig()->splitOn(true); rig()->splitOn();
} 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(true); rig()->splitOn();
} else if (rig()->isVFOB()) { } else if (rig()->isVFOB()) {
rig()->splitOff(true); rig()->splitOff();
} else { } else {
setSyntaxError(); setSyntaxError();
} }
@ -238,23 +238,19 @@ void TS590_MD::handleCommand(const char* cmd) {
break; break;
case '1': // LSB case '1': // LSB
rig()->selectLSB(true); rig()->setModeLSB();
rig()->cwOff(true);
break; break;
case '2': // USB case '2': // USB
rig()->selectUSB(true); rig()->setModeUSB();
rig()->cwOff(true);
break; break;
case '3': // CW case '3': // CW
rig()->selectUSB(true); rig()->setModeCW();
rig()->cwOn(true);
break; break;
case '7': // CW-R case '7': // CW-R
rig()->selectLSB(true); rig()->setModeCWR();
rig()->cwOn(true);
break; break;
default: default:
@ -266,18 +262,16 @@ void TS590_MD::handleCommand(const char* cmd) {
} }
void TS590_MD::sendResponse(const char* cmd) { void TS590_MD::sendResponse(const char* cmd) {
if (rig()->isCW()) { if (rig()->isModeCW()) {
if (rig()->isUSB()) { ts590SendCommand("MD3");
ts590SendCommand("MD3"); } else if (rig()->isModeCWR()) {
} else { ts590SendCommand("MD7");
ts590SendCommand("MD7"); } else if (rig()->isModeUSB()) {
} ts590SendCommand("MD2");
} else if (rig()->isModeLSB()) {
ts590SendCommand("MD1");
} else { } else {
if (rig()->isUSB()) { ts590SendCommand("MD0");
ts590SendCommand("MD2");
} else {
ts590SendCommand("MD1");
}
} }
} }

View File

@ -110,9 +110,9 @@ class TS590_FAB : public TS590Command {
if (strlen(cmd) == 13) { if (strlen(cmd) == 13) {
unsigned long freq = strtoul(&cmd[2], NULL, 10); unsigned long freq = strtoul(&cmd[2], NULL, 10);
if (VFOA) { if (VFOA) {
rig()->setFreqA(freq, true); rig()->setFreqA(freq);
} else { } else {
rig()->setFreqB(freq, true); rig()->setFreqB(freq);
} }
} else { } else {
setSyntaxError(); setSyntaxError();