diff --git a/Raduino/ubitx_ui.ino b/Raduino/ubitx_ui.ino index e7b9212..3c975e6 100644 --- a/Raduino/ubitx_ui.ino +++ b/Raduino/ubitx_ui.ino @@ -18,7 +18,7 @@ const PROGMEM uint8_t meters_bitmap[] = { }; */ -#include "RigState.h" +//#include "RigState.h" //SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA diff --git a/TeensyDSP/RigState.cpp b/TeensyDSP/RigState.cpp index 37adef0..44e7bb8 100644 --- a/TeensyDSP/RigState.cpp +++ b/TeensyDSP/RigState.cpp @@ -5,6 +5,8 @@ #ifndef TEENSYDUINO +#include "ubitx_eemap.h" + extern unsigned long frequency; extern unsigned long vfoA; extern unsigned long vfoB; @@ -15,123 +17,46 @@ 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) { +/*! + * @brief Write dirty fields from the provided rig state, out to the + * Raduino variables. + * @param r + * Reference to a RigState object that will be used to update + * the Raduino variables. + */ +void writeDirty(const RigState& r) { + // VFO A frequency + if (r.isDirty(VFOA_WORD)) { if (vfoActive == VFO_A) { - setFrequency(d); + setFrequency(r.getFreqA()); } else { - vfoA = frequency; - } + vfoA = r.getFreqA(); + } } -}; -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) { + // VFO B frequency + if (r.isDirty(VFOB_WORD)) { if (vfoActive == VFO_B) { - setFrequency(d); + setFrequency(r.getFreqB()); } else { - vfoB = frequency; - } + vfoB = r.getFreqB(); + } } -}; -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; + // RIT and XIT frequencies + if (r.isDirty(OFFSETS_WORD)) { + // RIT + ritRxFrequency = r.getRIT() + ritTxFrequency; if ((ritOn == 1) && (inTx == 0)) { setFrequency(ritRxFrequency); } + // XIT - TODO } -}; -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) { + // VFO A/B selection + if (r.isDirty(FLAGS_WORD)) { char prev = vfoActive; - vfoActive = (d & UBITX_VFOB_FLAG ? VFO_B : VFO_A); + vfoActive = r.isVFOA() ? VFO_A : VFO_B; if (vfoActive != prev) { if (vfoActive == VFO_A) { if (vfoA != frequency) { @@ -143,29 +68,129 @@ struct writeFlags { } } } - - splitOn = d & UBITX_SPLIT_FLAG ? 1 : 0; - - prev = ritOn; - ritOn = d & UBITX_RIT_FLAG ? 1 : 0; + + // Split on/off + splitOn = r.isSplit() ? 1 : 0; + + // RIT on/off + prev = ritOn; + ritOn = r.isRIT() ? 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 + + // XIT on/off + // TODO + + // Mode + prev = (cwMode << 1) | isUSB; + isUSB = r.isUSB() ? 1 : 0; + if (r.isCW()) { + cwMode = 2; // 2 = cwu + } else if (r.isCWR()) { + cwMode = 1; // 1 = cwl } else { - cwMode = 0; + cwMode = 0; // 0 = no cw } if ((cwMode << 1) | isUSB != prev) { - setFrequency(frequency); + setFrequency(frequency); } } -}; +} + +/*! + * @brief Read current Raduino variables into the provided RigState + * (if they are dirty) and set the appropriate dirty flags. + * @param r + * RigState reference to put the values into. + */ +void readDirty(RigState& r) { + unsigned freq; + short offset; + + // VFO A frequency + freq = (vfoActive == VFO_A) ? frequency : vfoA; + if (r.getFreqA() != freq) { + r.setFreqA(freq); + r.setDirty(VFOA_WORD); + } + + // VFO B frequency + freq = (vfoActive == VFO_B) ? frequency : vfoB; + if (r.getFreqB() != freq) { + r.setFreqB(freq); + r.setDirty(VFOB_WORD); + } + + // RIT frequency + offset = ritRxFrequency - frequency; + if (r.getRIT() != offset) { + r.setRIT(offset); + r.setDirty(OFFSETS_WORD); + } + + // XIT frequency + offset = 0; // xitRxFrequency - frequency; + if (r.getXIT() != offset) { + r.setXIT(offset); + r.setDirty(OFFSETS_WORD); + } + + bool dirty = false; + + // VFO A/B selection + if (r.isVFOA() && vfoActive == VFO_B) { + r.setVFOB(); + dirty = true; + } else if (r.isVFOB() && vfoActive == VFO_A) { + r.setVFOA(); + dirty = true; + } + + // Split selection + if (r.isSplit() && splitOn == 0) { + r.setSplitOff(); + dirty = true; + } else if (!r.isSplit() && splitOn != 0) { + r.setSplitOn(); + dirty = true; + } + + // RIT selection + if (r.isRIT() && ritOn == 0) { + r.setRITOff(); + dirty = true; + } else if (!r.isRIT() && ritOn != 0) { + r.setRITOn(); + dirty = true; + } + + // XIT selection + r.setXITOff(); + // TODO + + // Mode + char prev = (r.isCW() ? 4 : 0) | (r.isCWR() ? 2 : 0) | (r.isUSB() ? 1 : 0); + char curr = (cwMode << 1) | isUSB; + if (curr != prev) { + if (cwMode == 2) { + r.setCW(); + } else if (cwMode == 1) { + r.setCWR(); + } else { + if (isUSB) { + r.setUSB(); + } else { + r.setLSB(); + } + } + dirty = true; + } + + if (dirty) r.setDirty(FLAGS_WORD); +} #endif @@ -197,29 +222,17 @@ void RigState::begin() { } } -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 < numFields; i++) { - if (read(i)) { - makeDirty(i); - } - } - - // Next we need to send the current (changed) Raduino information - // to the TeensyDSP. +void updateRaduinoState(RigState& r) { + writeDirty(r); Wire.beginTransmission(I2CMETER_ADDR); Wire.write(I2CMETER_RIGINF); - 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); - } + for (RigStateWord i = 0; i < NUM_WORDS; i++) { + Wire.write((byte*)&r.data, sizeof(r.data)); // - write the field data + r.setClean(i); } Wire.endTransmission(); - delay(1); // some delay required between ending transmission and requesting? + delay(1); // 1ms - some delay required between ending transmission and requesting? // Retrieve all of the deltas. Mark any received field as dirty. Wire.requestFrom(I2CMETER_ADDR, numBytes); diff --git a/TeensyDSP/RigState.h b/TeensyDSP/RigState.h index 289be49..edb91d6 100644 --- a/TeensyDSP/RigState.h +++ b/TeensyDSP/RigState.h @@ -3,12 +3,6 @@ #include -#define UBITX_VFOA_UPDATE 0x00000001 -#define UBITX_VFOB_UPDATE 0x00000002 -#define UBITX_RIT_UPDATE 0x00000004 -#define UBITX_XIT_UPDATE 0x00000008 -#define UBITX_FLAGS_UPDATE 0x00000010 - #define UBITX_VFOB_FLAG 0x00000001 #define UBITX_SPLIT_FLAG 0x00000002 #define UBITX_RIT_FLAG 0x00000004 @@ -17,14 +11,68 @@ #define UBITX_USB_FLAG 0x00000020 #define UBITX_TX_FLAG 0x00000040 -struct UBitxRigState { - uint32_t header = 0; - uint32_t vfo[2]; - int32_t rit; - int32_t xit; - uint32_t flags = 0; +enum RigStateWord { + DIRTY_WORD = 0, + VFOA_WORD, + VFOB_WORD, + OFFSETS_WORD, + FLAGS_WORD, + NUM_WORDS }; +struct UBitxRigState { + uint32_t data[RigStateWord.NUM_WORDS] = {0}; + + /*! + * @brief Set the dirty bit for for the specified word. + */ + inline void setDirty(RigStateWord w) { + data[i] |= w < NUM_WORDS ? 1 << w : 0; + } + + inline void setClean(RigStateWord w) { + data[i] &= ~(w < NUM_WORDS ? 1 << w : 0); + } + + inline bool isDirty(RigStateWord w) { + return (1 << w) & data[DIRTY_WORD] > 0 ? true : false; + } + + inline void setFreqA(uint32_t freq) { data[VFOA_WORD] = freq; } + inline uint32_t getFreqA() const { return data[VFOA_WORD]; } + inline void getFreqB(uint32_r freq) { data[VFOB_WORD] = freq; } + inline uint32_t getFreqB() const { return data[VFOB_WORD]; } + inline void setRIT(int16_t offset) { data[OFFSETS_WORD] = (offset << 16) | (0x0000FFFF & data[OFFSETS_WORD]); } + inline int16_t getRIT() const { return data[OFFSETS_WORD] >> 16; } + inline void setXIT(int16_t offset) { data[OFFSETS_WORD] = (0xFFFF0000 & data[OFFSETS_WORD]) | offset; + inline int16_t getXIT() const { return 0x0000FFFF & data[OFFSETS_WORD]; } + inline void setVFOA() { data[FLAGS_WORD] &= ~UBITX_VFOB_FLAG; } + inline void setVFOB() { data[FLAGS_WORD] |= UBITX_VFOB_FLAG; } + inline bool isVFOA() const { return data[FLAGS_WORD] & UBITX_VFOB_FLAG ? false : true; } + inline bool isVFOB() const { return data[FLAGS_WORD] & UBITX_VFOB_FLAG ? true : false; } + inline void setSplitOn() { data[FLAGS_WORD] |= UBITX_SPLIT_FLAG; } + inline void setSplitOff() { data[FLAGS_WORD] &= ~UBITX_SPLIT_FLAG; } + inline bool isSplit() const { data[FLAGS_WORD] & UBITX_SPLIT_FLAG ? true : false; } + inline void setRITOn() { data[FLAGS_WORD] |= UBITX_RIT_FLAG; } + inline void setRITOff() { data[FLAGS_WORD] &= ~UBITX_RIT_FLAG; } + inline bool isRIT() const { data[FLAGS_WORD] & UBITX_RIT_FLAG ? true : false; } + inline void setXITOn() { data[FLAGS_WORD] |= UBITX_XIT_FLAG; } + inline void setXITOff() { data[FLAGS_WORD] &= ~UBITX_XIT_FLAG; } + inline bool isXIT() const { data[FLAGS_WORD] & UBITX_XIT_FLAG ? true : false; } + inline void setUSB() { data[FLAGS_WORD] |= UBITX_USB_FLAG; data[FLAGS_WORD] &= ~UBITX_CW_FLAG; } + inline void setLSB() { data[FLAGS_WORD] &= ~UBITX_USB_FLAG; data[FLAGS_WORD] &= ~UBITX_CW_FLAG; } + inline void setCW() { data[FLAGS_WORD] |= UBITX_USB_FLAG; data[FLAGS_WORD] |= UBITX_CW_FLAG; } + inline void setCWR() { data[FLAGS_WORD] &= ~UBITX_USB_FLAG; data[FLAGS_WORD] |= UBITX_CW_FLAG; } + inline bool isUSB() { return (data[FLAGS_WORD] & UBITX_USB_FLAG > 0) && (data[FLAGS_WORD] & UBITX_CW_FLAG == 0); } + inline bool isLSB() { return (data[FLAGS_WORD] & UBITX_USB_FLAG == 0) && (data[FLAGS_WORD] & UBITX_CW_FLAG == 0); } + inline bool isCW() { return (data[FLAGS_WORD] & UBITX_USB_FLAG > 0) && (data[FLAGS_WORD] & UBITX_CW_FLAG > 0); } + inline bool isCWR() { return (data[FLAGS_WORD] & UBITX_USB_FLAG == 0) && (data[FLAGS_WORD] & UBITX_CW_FLAG > 0); } +}; + +#ifndef TEENSYDUINO +void mergeDirty(const RigState& r); +#endif + /**********************************************************************/ // NEW IMPLEMENTATION @@ -58,7 +106,6 @@ struct Field : public BaseField { 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