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:
inline void begin() {}
inline void update() {}
inline unsigned long getFreqA() const { return state.vfo[0]; }
inline unsigned long getFreqB() const { return state.vfo[1]; }
inline long getRIT() const { return state.rit; }
inline long getXIT() const { return state.xit; }
inline bool isVFOA() const { return (state.flags & UBITX_VFOB_FLAG) != UBITX_VFOB_FLAG; }
inline bool isVFOB() const { return (state.flags & UBITX_VFOB_FLAG) == UBITX_VFOB_FLAG; }
inline bool isSplit() const { return (state.flags & UBITX_SPLIT_FLAG) == UBITX_SPLIT_FLAG; }
inline bool isRITOn() const { return (state.flags & UBITX_RIT_FLAG) == UBITX_RIT_FLAG; }
inline bool isXITOn() const { return (state.flags & UBITX_XIT_FLAG) == UBITX_XIT_FLAG; }
inline bool isCW() const { return (state.flags & UBITX_CW_FLAG) == UBITX_CW_FLAG; }
inline bool isLSB() const { return (state.flags & UBITX_USB_FLAG) != UBITX_USB_FLAG; }
inline bool isUSB() const { return (state.flags & UBITX_USB_FLAG) == UBITX_USB_FLAG; }
inline bool getAI() const { return autoInfo; }
inline bool updatedByCAT() const { return lastUpdatedBy == CATSource; }
inline bool updatedByRaduino() const { return lastUpdatedBy == RaduinoSource; }
inline unsigned getFreqA() const { return catState.getFreqA(); }
inline unsigned getFreqB() const { return catState.getFreqB(); }
inline int getRIT() const { return catState.getRIT(); }
inline int getXIT() const { return catState.getXIT(); }
inline bool isVFOA() const { return catState.isVFOA(); }
inline bool isVFOB() const { return catState.isVFOB(); }
inline bool isSplit() const { return catState.isSplit(); }
inline bool isRITOn() const { return catState.isRITOn(); }
inline bool isXITOn() const { return catState.isXITOn(); }
inline bool isModeCW() const { return catState.isCW() && catState.isUSB(); }
inline bool isModeCWR() const { return catState.isCW() && catState.isLSB(); }
inline bool isModeUSB() const { return catState.isUSB() && !catState.isCW(); }
inline bool isModeLSB() const { return catState.isLSB() && !catState.isCW(); }
inline bool isAI() const { return autoInfo; }
//inline bool updatedByCAT() const { return lastUpdatedBy == CATSource; }
//inline bool updatedByRaduino() const { return lastUpdatedBy == RaduinoSource; }
inline void clearUpdate() { lastUpdatedBy = NoSource; }
inline void setRaduinoUpdate() { lastUpdatedBy = RaduinoSource; }
inline void setCATUpdate() { lastUpdatedBy = CATSource; }
//inline void clearUpdate() { lastUpdatedBy = NoSource; }
//inline void setRaduinoUpdate() { lastUpdatedBy = RaduinoSource; }
//inline void setCATUpdate() { lastUpdatedBy = CATSource; }
inline void setFreqA(unsigned long freq, bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.vfo[0] = freq;
}
inline void setFreqB(unsigned long freq, bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.vfo[1] = freq;
}
inline void setRIT(short offset, bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.rit = offset;
}
inline void setXIT(short offset, bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.xit = offset;
}
inline void selectVFOA(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags &= ~UBITX_VFOB_FLAG;
}
inline void selectVFOB(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags |= UBITX_VFOB_FLAG;
}
inline void toggleVFO(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags ^= UBITX_VFOB_FLAG;
}
inline void splitOn(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags |= UBITX_SPLIT_FLAG;
}
inline void splitOff(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags &= ~UBITX_SPLIT_FLAG;
}
inline void ritOn(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags |= UBITX_RIT_FLAG;
}
inline void ritOff(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags &= ~UBITX_RIT_FLAG;
}
inline void xitOn(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags |= UBITX_XIT_FLAG;
}
inline void xitOff(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags &= ~UBITX_XIT_FLAG;
}
inline void cwOn(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags |= UBITX_CW_FLAG;
}
inline void cwOff(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags &= ~UBITX_CW_FLAG;
}
inline void selectLSB(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags &= ~UBITX_USB_FLAG;
}
inline void selectUSB(bool isCAT = false) {
lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
state.flags |= UBITX_USB_FLAG;
}
inline void 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 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 aiOn() { autoInfo = true; }
inline void aiOff() { autoInfo = false; }
uint8_t* const stateAsBytes() const { return (uint8_t* const)&state; }
inline void updateState(UBitxRigState& r, bool isCAT = false) {
if ((r.vfo[0] == state.vfo[0]) &&
(r.vfo[1] == state.vfo[1]) &&
@ -150,7 +82,8 @@ class UBitxRig {
private:
bool autoInfo = false;
UpdateSource lastUpdatedBy = NoSource;
UBitxRigState state;
UBitxRigState catState;
UBitxRigState radState;
};
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
/**********************************************************************/
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 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--;
}
}
}
extern unsigned long frequency;
extern unsigned long vfoA;
extern unsigned long vfoB;
extern char cwMode;
extern char isUSB;
extern char vfoActive;
extern char ritOn;
extern char splitOn;
void setFrequency(unsigned long);
#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 *

View File

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

View File

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

View File

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