ubitx-v5x/TeensyDSP/RigState.cpp

458 lines
12 KiB
C++

#include "RigState.h"
/**********************************************************************/
// Handle the case of the TeensyDSP.
#ifdef 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--;
}
}
}
#endif
/**********************************************************************
* EOF *
**********************************************************************/