From 8a416608a1c7381019cedf465879b3907678886d Mon Sep 17 00:00:00 2001 From: Rob French Date: Sun, 14 Feb 2021 23:04:29 -0600 Subject: [PATCH] Long way from being compilable on either the Raduino or the TeensyDSP. Lot of changes in progress. --- TeensyDSP/Rig.h | 143 ++------ TeensyDSP/RigState.cpp | 803 ++++++++++++++++++----------------------- TeensyDSP/RigState.h | 186 ++++------ TeensyDSP/TS590.cpp | 50 ++- TeensyDSP/TS590.h | 4 +- 5 files changed, 489 insertions(+), 697 deletions(-) diff --git a/TeensyDSP/Rig.h b/TeensyDSP/Rig.h index ff3a911..88c0239 100644 --- a/TeensyDSP/Rig.h +++ b/TeensyDSP/Rig.h @@ -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; diff --git a/TeensyDSP/RigState.cpp b/TeensyDSP/RigState.cpp index 6bab7e6..2a0fa8a 100644 --- a/TeensyDSP/RigState.cpp +++ b/TeensyDSP/RigState.cpp @@ -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(), + new Field(), + new Field(), + new Field(), + new Field(), + new Field(), +}; + +/**********************************************************************/ + +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 * diff --git a/TeensyDSP/RigState.h b/TeensyDSP/RigState.h index 1bbe300..b1d2b25 100644 --- a/TeensyDSP/RigState.h +++ b/TeensyDSP/RigState.h @@ -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 void writeChanges() { - if (dirty) { - STREAM().write(id); - STREAM().write((byte*)&data, sizeof(T)); - } - } - - template 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 +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 void writeChanges() { - vfoA.writeChanges(); - vfoB.writeChanges(); - rit.writeChanges(); - xit.writeChanges(); - flags.writeChanges(); - } - - template void readChanges(size_t size) { - size_t len = 0; - while (STREAM().available() && len < size) { - switch(STREAM().read()) { - case 0: - len += vfoA.read(); - break; - - case 1: - len += vfoB.read(); - break; - - case 2: - len += rit.read(); - break; - - case 3: - len += xit.read(); - break; - - case 4: - len += flags.read(); - 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; diff --git a/TeensyDSP/TS590.cpp b/TeensyDSP/TS590.cpp index a4fac4b..d073c0f 100644 --- a/TeensyDSP/TS590.cpp +++ b/TeensyDSP/TS590.cpp @@ -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"); } } diff --git a/TeensyDSP/TS590.h b/TeensyDSP/TS590.h index e941c8d..2f1b6a4 100644 --- a/TeensyDSP/TS590.h +++ b/TeensyDSP/TS590.h @@ -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();