2021-02-05 23:59:31 -05:00
|
|
|
#ifndef __RigState_h__
|
|
|
|
#define __RigState_h__
|
|
|
|
|
2021-02-07 00:45:19 -05:00
|
|
|
#include <Arduino.h>
|
|
|
|
|
2021-02-09 23:58:07 -05:00
|
|
|
#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
|
2021-02-05 23:59:31 -05:00
|
|
|
|
2021-02-09 23:58:07 -05:00
|
|
|
#define UBITX_VFOB_FLAG 0x00000001
|
|
|
|
#define UBITX_SPLIT_FLAG 0x00000002
|
|
|
|
#define UBITX_RIT_FLAG 0x00000004
|
|
|
|
#define UBITX_XIT_FLAG 0x00000008
|
|
|
|
#define UBITX_CW_FLAG 0x00000010
|
|
|
|
#define UBITX_USB_FLAG 0x00000020
|
|
|
|
#define UBITX_TX_FLAG 0x00000040
|
2021-02-05 23:59:31 -05:00
|
|
|
|
|
|
|
struct UBitxRigState {
|
2021-02-09 23:58:07 -05:00
|
|
|
uint32_t header = 0;
|
2021-02-05 23:59:31 -05:00
|
|
|
uint32_t vfo[2];
|
2021-02-09 23:58:07 -05:00
|
|
|
int32_t rit;
|
|
|
|
int32_t xit;
|
|
|
|
uint32_t flags = 0;
|
2021-02-05 23:59:31 -05:00
|
|
|
};
|
|
|
|
|
2021-02-11 23:00:24 -05:00
|
|
|
/**********************************************************************/
|
2021-02-14 01:35:38 -05:00
|
|
|
// NEW IMPLEMENTATION
|
2021-02-11 23:00:24 -05:00
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
struct BaseField {
|
|
|
|
BaseField(): dirty(false), data(0) {}
|
|
|
|
virtual ~BaseField() = 0;
|
|
|
|
|
2021-02-11 23:00:24 -05:00
|
|
|
bool dirty;
|
2021-02-14 01:35:38 -05:00
|
|
|
uint32_t data;
|
2021-02-11 23:00:24 -05:00
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
virtual bool read() = 0;
|
|
|
|
virtual void write() const = 0;
|
|
|
|
};
|
2021-02-11 23:00:24 -05:00
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
template<typename R, typename W>
|
2021-02-15 23:38:05 -05:00
|
|
|
struct Field : public BaseField {
|
2021-02-15 00:04:29 -05:00
|
|
|
/*!
|
|
|
|
* @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); }
|
2021-02-11 23:00:24 -05:00
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
/*!
|
|
|
|
* @brief Using the supplied write function, which should take
|
|
|
|
* data as its input, write data to some destination.
|
|
|
|
*/
|
|
|
|
virtual void write() const { W(data); }
|
2021-02-11 23:00:24 -05:00
|
|
|
};
|
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
#define WIREBUS_NULL 0 // an empty field
|
2021-02-14 01:35:38 -05:00
|
|
|
#define WIREBUS_VFO_A 1
|
|
|
|
#define WIREBUS_VFO_B 2
|
|
|
|
#define WIREBUS_RIT_OFS 3
|
|
|
|
#define WIREBUS_XIT_OFS 4
|
|
|
|
#define WIREBUS_FLAGS 5
|
|
|
|
#define WIREBUS_NUM_FIELDS 6
|
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
class RigState {
|
|
|
|
public:
|
|
|
|
RigState(BaseField** f = NULL, int numf = 0): field(f), numFields(numf), numDirty(0) {}
|
2021-02-14 01:35:38 -05:00
|
|
|
void begin();
|
|
|
|
void update();
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Read in the specified (by index) external value, and use
|
|
|
|
* it to update the rig state.
|
|
|
|
*/
|
|
|
|
inline bool read(byte i) {
|
2021-02-15 00:04:29 -05:00
|
|
|
return field[i]->read();
|
2021-02-14 01:35:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief Use the specified (vy index) rig state field to update the
|
|
|
|
* external value.
|
|
|
|
*/
|
|
|
|
inline void write(byte i) {
|
2021-02-15 00:04:29 -05:00
|
|
|
field[i]->write();
|
2021-02-14 01:35:38 -05:00
|
|
|
}
|
2021-02-11 23:00:24 -05:00
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
inlie bool isDirty(byte i) {
|
|
|
|
return field[i]->dirty();
|
2021-02-11 23:00:24 -05:00
|
|
|
}
|
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
inline void makeDirty(byte i) {
|
|
|
|
if (!field[i]->dirty) {
|
|
|
|
field[i]->dirty = true;
|
|
|
|
numDirty++;
|
|
|
|
}
|
2021-02-11 23:00:24 -05:00
|
|
|
}
|
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
inline void makeClean(byte i) {
|
|
|
|
if (field[i]->dirty) {
|
|
|
|
field[i]->dirty = false;
|
|
|
|
numDirty--;
|
2021-02-11 23:00:24 -05:00
|
|
|
}
|
|
|
|
}
|
2021-02-15 00:04:29 -05:00
|
|
|
|
|
|
|
inline byte* data(byte i) {
|
|
|
|
return (byte*)(&(field[i]->data));
|
2021-02-11 23:00:24 -05:00
|
|
|
}
|
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
inline int dataSize(byte i) {
|
|
|
|
return sizeof(field[i]->data);
|
2021-02-11 23:00:24 -05:00
|
|
|
}
|
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
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;
|
|
|
|
};
|
2021-02-14 01:35:38 -05:00
|
|
|
|
2021-02-15 00:04:29 -05:00
|
|
|
#ifndef TEENSYDUINO
|
2021-02-14 01:35:38 -05:00
|
|
|
|
|
|
|
extern RigState rigState;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2021-02-11 23:00:24 -05:00
|
|
|
/*
|
|
|
|
Protocol discussion:
|
|
|
|
- I2C master: Raduino
|
|
|
|
- I2C slave: TeensyDSP
|
|
|
|
|
|
|
|
Raduino state:
|
|
|
|
- Baseline uBITX variables
|
|
|
|
- I2C buffer
|
|
|
|
- On I2C transmit: make updates based on current variables
|
|
|
|
- On I2C receive:
|
|
|
|
- Update based on received I2C responses
|
|
|
|
- Update associated variables
|
|
|
|
|
|
|
|
TeensyDSP state:
|
|
|
|
- CAT buffer
|
|
|
|
- Used to receive command from CAT (when commands arrive via Serial)
|
|
|
|
- Used to transmit state to Raduino (when requested via Wire1)
|
|
|
|
- Raduino buffer
|
|
|
|
- Used to receive state from Raduino (when received via Wire1)
|
|
|
|
- Used to transmit responses to CAT (over Serial)
|
|
|
|
- Questions
|
|
|
|
- How can these be synchronized?
|
|
|
|
- At the tail end of an I2C request handler. Before sending the response to the Raduino via I2C:
|
|
|
|
- Copy updated CAT buffer items to the Raduino buffer.
|
|
|
|
- Copy updated Raduino buffer items to the CAT buffer.
|
|
|
|
- In the case of conflicts, CAT wins.
|
|
|
|
- Transmit the CAT buffer state to the Raduino.
|
|
|
|
- TeensyDSP updates 'outgoing' state based on CAT inputs.
|
|
|
|
- Make change to data.
|
|
|
|
- Mark data as dirty, if different than incoming state.
|
|
|
|
- When requested, Teensy DSP sends 'outgoing' state to Raduino.
|
|
|
|
- Send dirty data over I2C.
|
|
|
|
- Mark data as clean.
|
|
|
|
*/
|
|
|
|
|
2021-02-05 23:59:31 -05:00
|
|
|
#endif
|