Fixed comms between the Raduino and the IOP. Implemented the wrapper

that allows messages to go back from the IOP to Raduino.  I don't know
if actual CAT from the PC works currently, however.
This commit is contained in:
Rob French 2020-05-18 08:16:54 -05:00
parent ccae79925b
commit 9c1a490963
7 changed files with 248 additions and 100 deletions

View File

@ -16,6 +16,16 @@
//======================================================================
void sendCATMessage(const uint8_t* buf)
{
MYSERIAL.write(prefixAndLengthToByte(CAT_PREFIX, 5));
for (int i = 0; i < 5; i++) {
MYSERIAL.write(buf[i]);
}
}
//======================================================================
void sendIOPMessage(IOPMessage const& msg)
{
MYSERIAL.write(prefixAndLengthToByte(IOP_PREFIX, msg.len + 1));
@ -77,6 +87,70 @@ void sendIOPModeRequest()
sendIOPMessage(m);
}
//======================================================================
// SSB STATUS MESSAGE
//======================================================================
void sendIOPSSBStatus(SSBConfig const &c)
{
IOPMessage m;
m.id = IOP_SSB_STATUS_MSG;
m.len = 4;
m.data[0] = 'S'; // current mode; redundant w/ Raduino mode, but maybe useful for debugging
m.data[1] = '-'; // placeholder for transmit filter/compressor
m.data[2] = RX_FILTER_LETTER[c.filter];
m.data[3] = '\0';
sendIOPMessage(m);
}
//======================================================================
// DIGI STATUS MESSAGE
//======================================================================
void sendIOPDigiStatus(DigiConfig const &c)
{
IOPMessage m;
m.id = IOP_DIGI_STATUS_MSG;
m.len = 4;
m.data[0] = 'D'; // current mode; redundant w/ Raduino mode, but maybe useful for debugging
m.data[1] = '-'; // placeholder for future digital submodes?
m.data[2] = RX_FILTER_LETTER[c.filter];
m.data[3] = '\0';
sendIOPMessage(m);
}
//======================================================================
// CW STATUS MESSAGE
//======================================================================
void sendIOPCWStatus(CWConfig const &c)
{
IOPMessage m;
m.id = IOP_CW_STATUS_MSG;
m.len = 4;
m.data[0] = 'C'; // current mode; redundant w/ Raduino mode, but maybe useful for debugging
m.data[1] = KEYER_MODE_LETTER[c.mode];
m.data[2] = RX_FILTER_LETTER[c.filter];
m.data[3] = '\0';
sendIOPMessage(m);
}
//======================================================================
// TEST STATUS MESSAGE
//======================================================================
void sendIOPTestStatus()
{
IOPMessage m;
m.id = IOP_TEST_STATUS_MSG;
m.len = 4;
m.data[0] = ' ';
m.data[1] = 'T';
m.data[2] = 'T';
m.data[3] = '\0';
sendIOPMessage(m);
}
//======================================================================
/*

View File

@ -70,7 +70,10 @@ enum MessageID {
// Requests
IOP_MODE_REQUEST,
IOP_SSB_STATUS_MSG,
IOP_DIGI_STATUS_MSG,
IOP_CW_STATUS_MSG,
IOP_TEST_STATUS_MSG,
// add any new elements here
NUM_MESSAGE_IDS
@ -92,10 +95,10 @@ enum MessageID {
*/
enum RigMode {
MODE_SSB = 0,
MODE_DIGI,
MODE_CW,
MODE_TEST,
RIG_MODE_SSB = 0,
RIG_MODE_DIGI,
RIG_MODE_CW,
RIG_MODE_TEST,
// add any new elements here
NUM_RIG_MODES
};
@ -103,17 +106,26 @@ enum RigMode {
/* Keyer modes.
*/
enum KeyMode {
STRAIGHT = 0,
IAMBIC_A,
IAMBIC_B,
//ULTIMATIC,
//BUG,
enum KeyerMode {
KEYER_MODE_STRAIGHT = 0,
KEYER_MODE_IAMBIC_A,
KEYER_MODE_IAMBIC_B,
//KEYER_ULTIMATIC,
//KEYER_BUG,
// add any new elements here
NUM_KEY_MODES
NUM_KEYER_MODES
};
const unsigned char MODE_LETTER[3] = {'S', 'A', 'B'};
enum RxFilter {
RX_FILTER_NORMAL = 0,
RX_FILTER_NARROW,
RX_FILTER_WIDE,
NUM_RX_FILTERS
};
const unsigned char RIG_MODE_LETTER[NUM_RIG_MODES] = {'S', 'D', 'C', 'T'};
const unsigned char KEYER_MODE_LETTER[NUM_KEYER_MODES] = {'S', 'A', 'B'};
const unsigned char RX_FILTER_LETTER[NUM_RX_FILTERS] = {'-', 'N', 'W'};
const uint8_t NO_FLAGS = 0;
const uint8_t REVERSED = 1;
@ -124,30 +136,58 @@ struct IOPMessage {
uint8_t data[IOP_MESSAGE_MAX_LEN];
};
//======================================================================
// SSB CONFIGURATION
//======================================================================
void sendIOPMessage(IOPMessage const&);
void recvIOPMessage(IOPMessage&, const uint8_t*, int);
struct SSBConfig {
// parameters
RxFilter filter = RX_FILTER_NORMAL;
};
void sendIOPModeCommand(RigMode);
void sendIOPStartTxCommand();
void sendIOPStopTxCommand();
void sendIOPModeRequest();
//======================================================================
// DIGI CONFIGURATION
//======================================================================
struct DigiConfig {
// parameters
RxFilter filter = RX_FILTER_NORMAL;
};
//======================================================================
// CW CONFIGURATION
//======================================================================
struct CWConfig {
// mode
KeyMode mode = IAMBIC_A;
// flags
bool reversed = false;
// parameters
uint8_t wpm = 15;
float weight = 3.0;
uint16_t sidetone = 700;
// mode
KeyerMode mode = KEYER_MODE_IAMBIC_A;
// flags
bool reversed = false;
// parameters
uint8_t wpm = 15;
float weight = 3.0;
uint16_t sidetone = 700;
RxFilter filter = RX_FILTER_NORMAL;
};
//======================================================================
// FUNCTION PROTOTYPES
//======================================================================
void sendCATMessage(const uint8_t*);
void sendIOPMessage(IOPMessage const&);
void recvIOPMessage(IOPMessage&, const uint8_t*, int);
void sendIOPModeCommand(RigMode);
void sendIOPStartTxCommand();
void sendIOPStopTxCommand();
void sendIOPModeRequest();
void sendIOPSSBStatus(SSBConfig const&);
void sendIOPDigiStatus(DigiConfig const&);
void sendIOPCWStatus(CWConfig const&);
void sendIOPTestStatus();
//======================================================================
// TRANSLATOR
//======================================================================
@ -187,23 +227,6 @@ class Translator
};
*/
//======================================================================
// CW STATUS MESSAGE
//======================================================================
//void packT_DisplayText(TMessage &m, CWConfig const &c)
//{
// m.id = IOP_CW_STATUS_MSG;
// m.len = 3;
// m.data[0] = ' '; // growth
// m.data[1] = MODE_LETTER[c.mode];
// m.data[2] = ' '; // TODO: RX filter width
//}
// No unpack required: this is a string to put on the display.
//======================================================================
#endif
//======================================================================

View File

@ -304,10 +304,10 @@ void audioTransmit()
{
switch(rigMode) {
// Nothing special for CW, TX audio inputs are already muted.
//case MODE_CW:
//case RIG_MODE_CW:
//break;
case MODE_SSB:
case RIG_MODE_SSB:
// Mute the incoming RX audio. Can't think of a good reason
// to let RX audio in while we're transmitting.
muteRxRigIn();
@ -335,14 +335,14 @@ void audioTransmit()
}
break;
case MODE_DIGI:
case RIG_MODE_DIGI:
// Mute the incoming RX audio. Can't think of a good reason
// to let RX audio in while we're transmitting.
muteRxRigIn();
updateTxUSBIn();
break;
case MODE_TEST:
case RIG_MODE_TEST:
muteRxRigIn();
updateTxTwoToneIn();
break;
@ -359,10 +359,10 @@ void audioTransmit()
void audioReceive()
{
switch(rigMode) {
//case MODE_CW:
//case RIG_MODE_CW:
//break;
case MODE_SSB:
case RIG_MODE_SSB:
if (audioTxInput == TX_MIC_IN) {
muteTxMicIn();
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
@ -372,12 +372,12 @@ void audioReceive()
restoreRxRigIn();
break;
case MODE_DIGI:
case RIG_MODE_DIGI:
muteTxUSBIn();
restoreRxRigIn();
break;
case MODE_TEST:
case RIG_MODE_TEST:
muteTxTwoToneIn();
restoreRxRigIn();
break;

View File

@ -30,16 +30,12 @@ void initCAT(long baud, int portConfig)
// CAT with PC via USB
USBSERIAL.begin(baud);
USBSERIAL.flush();
#if defined(DEBUG)
USBSERIAL.println("IOP: opened USB serial port (to PC)");
#endif
USBDEBUG("opened USB serial port (to PC)");
// Comm (including CAT passthru) with Raduino via UART
HWSERIAL.begin(baud, portConfig);
HWSERIAL.flush();
#if defined(DEBUG)
USBSERIAL.println("IOP: opened H/W serial port (to Raduino)");
#endif
USBDEBUG("opened H/W serial port (to Raduino)");
//sendIOPModeRequest(); // Raduino doesn't support this yet
}
@ -54,19 +50,19 @@ void processIOPCommand(IOPMessage const& m)
if (m.len < 1) {
return;
} else {
setRigMode(m.data[0]);
setRigMode(RigMode(m.data[0]));
#if defined(DEBUG)
switch(rigMode) {
case MODE_CW:
case RIG_MODE_CW:
USBDEBUG("new mode - CW");
break;
case MODE_SSB:
case RIG_MODE_SSB:
USBDEBUG("new mode - SSB");
break;
case MODE_DIGI:
case RIG_MODE_DIGI:
USBDEBUG("new mode - DIGI");
break;
case MODE_TEST:
case RIG_MODE_TEST:
USBDEBUG("new mode - TEST");
break;
}
@ -126,8 +122,8 @@ enum SerialState {
EEPROM_WRITE,
} serialState = NORMAL;
uint8_t readPrefix = 0;
uint8_t readLength = 0;
PrefixID readPrefix;
uint8_t readLength;
int cmdLength = 0;
byte cmdBuffer[16];
@ -139,13 +135,37 @@ int magicFlag = 0;
//----------------------------------------------------------------------
uint8_t usbCatLength = 0;
byte usbCatBuffer[5];
elapsedMillis usbCatTimer;
#define CAT_RECEIVE_TIMEOUT 500
void serviceCAT()
{
uint8_t incomingByte;
if ((usbCatLength > 0) && (usbCatTimer > CAT_RECEIVE_TIMEOUT)) {
// timeout... clear the buffer and start over
usbCatLength = 0;
usbCatTimer = 0;
}
// read from the USB serial, pass through to UART serial
for (int i = 0; i < USBSERIAL.available(); i++) {
for (int i = 0; i < USBSERIAL.available(); i++) {
incomingByte = USBSERIAL.read();
usbCatTimer = 0;
#if not defined(FACTORY_CALIBRATION)
usbCatBuffer[usbCatLength++] = incomingByte;
if (usbCatLength == 5) {
sendCATMessage(usbCatBuffer);
usbCatLength = 0;
}
// NOTE: This code does NOT handle any interrupts in COMMS from the PC...
#endif
#if defined(FACTORY_CALIBRATION)
// unless we're in factory calibration mode, in which case we're going
@ -176,7 +196,7 @@ void serviceCAT()
#else
// Don't pass CAT commands through if in DEBUG mode.
#if not defined(DEBUG)
HWSERIAL.write(incomingByte);
//HWSERIAL.write(incomingByte);
#endif
}

View File

@ -13,7 +13,7 @@
// Uncomment to use the "factory" calibration mode. This is intended to
// allow calibration of IOP settings, separately from the uBITX/Raduino.
// There will be no pass-thru of any CAT.
#define FACTORY_CALIBRATION
//#define FACTORY_CALIBRATION
// IOPConfig
// Used to store configuration parameters during runtime, as well as to
@ -84,11 +84,17 @@ struct IOPConfig {
float txSine2Vol = 1.0;
// rig-out parameters (TX) - default settings are based on hitting 70% of 25mVrms w/ mic
uint8_t txRigOutLevel = 31;
float txRigOutCal = 0.043;
float txRigOutCal = 0.1; // 0.061;
// USB-out parameters (TX)- debug/monitor use only
bool txUSBOutEnable = true;
float txUSBOutCal = 1.0;
// SSB configuration
SSBConfig ssb;
// Digi configuration
DigiConfig digi;
// CW configuration
CWConfig cw;
};

View File

@ -12,7 +12,7 @@
#include "keyer.h"
// comment this out to disable debugging code
//#define DEBUG
#define DEBUG
#if defined(DEBUG)
#define USBDEBUG(x) USBSERIAL.print("IOP: "); USBSERIAL.println(x);

View File

@ -8,7 +8,8 @@
#include <Bounce2.h>
#define BOUNCE_WITH_PROMPT_DETECTION
RigMode rigMode = MODE_SSB;
RigMode rigMode = RIG_MODE_SSB;
RxFilter rxFilter = RX_FILTER_NORMAL;
IOPConfig iopConfig;
#define MIC_PTT_PIN 21
@ -44,10 +45,10 @@ void catPTTOn()
// CAT should not start or stop TX in CW mode... we really should
// not even get this command. But maybe the rig control software is
// doing it (but then, we should inhibit this in the Raduino).
//case MODE_CW:
//case RIG_MODE_CW:
//break;
case MODE_SSB:
case RIG_MODE_SSB:
// In SSB mode, CAT-PTT will always (de-)activate the Line-In TX
// audio source.
txState = TX_CAT;
@ -56,7 +57,7 @@ void catPTTOn()
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_DIGI:
case RIG_MODE_DIGI:
// In Digital (USB) mode, CAT-PTT will always (de-)activate the
// USB-In TX audio source.
txState = TX_CAT;
@ -82,10 +83,10 @@ void catPTTOff()
// CAT should not start or stop TX in CW mode... we really should
// not even get this command. But maybe the rig control software is
// doing it (but then, we should inhibit this in the Raduino).
//case MODE_CW:
//case RIG_MODE_CW:
//break;
case MODE_SSB:
case RIG_MODE_SSB:
// In SSB mode, CAT-PTT will always (de-)activate the Line-In TX
// audio source.
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
@ -93,7 +94,7 @@ void catPTTOff()
txState = TX_OFF;
break;
case MODE_DIGI:
case RIG_MODE_DIGI:
// In Digital (USB) mode, CAT-PTT will always (de-)activate the
// USB-In TX audio source.
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
@ -115,39 +116,35 @@ void checkMicPTT()
// was released--the Mic-PTT can always be used to terminate a
// transmission from another source.
if ((txState != TX_OFF) && micPTT.rose()) {
#if defined(DEBUG)
USBSERIAL.println("DEBUG: mic PTT released");
#endif
USBDEBUG("mic PTT released");
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
// In CW mode, we get a sidetone from the uBITX, so we don't mute
// the receive audio.
if (rigMode != MODE_CW) audioReceive();
if (rigMode != RIG_MODE_CW) audioReceive();
txState = TX_OFF;
return;
}
if ((txState == TX_OFF) && micPTT.fell()) {
#if defined(DEBUG)
USBSERIAL.println("DEBUG: mic PTT depressed");
#endif
USBDEBUG("mic PTT depressed");
switch(rigMode) {
case MODE_CW:
case RIG_MODE_CW:
txState = TX_MIC;
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_SSB:
case RIG_MODE_SSB:
txState = TX_MIC;
audioSelectTxInput(TX_MIC_IN);
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_DIGI:
case RIG_MODE_DIGI:
// Mic PTT actuation during Digital does nothing.
break;
case MODE_TEST:
case RIG_MODE_TEST:
txState = TX_MIC;
audioSelectTxInput(TX_TEST_IN);
audioTransmit();
@ -172,30 +169,30 @@ void checkLinePTT()
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
// In CW mode, we get a sidetone from the uBITX, so we don't mute
// the receive audio.
if (rigMode != MODE_CW) audioReceive();
if (rigMode != RIG_MODE_CW) audioReceive();
txState = TX_OFF;
return;
}
if ((txState == TX_OFF) && linePTT.fell()) {
switch(rigMode) {
case MODE_CW:
case RIG_MODE_CW:
txState = TX_LINE;
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_SSB:
case RIG_MODE_SSB:
txState = TX_LINE;
audioSelectTxInput(TX_LINE_IN);
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_DIGI:
case RIG_MODE_DIGI:
// Line PTT actuation during Digital does nothing.
break;
case MODE_TEST:
case RIG_MODE_TEST:
txState = TX_LINE;
audioSelectTxInput(TX_TEST_IN);
audioTransmit();
@ -212,8 +209,8 @@ void setRigMode(RigMode m)
rigMode = m;
switch(rigMode) {
case MODE_SSB:
case MODE_TEST:
case RIG_MODE_SSB:
case RIG_MODE_TEST:
// SSB sets the TX audio input to line-in. Note that this will be
// automatically overridden by mic-in, if the mic PTT is pressed.
audioSelectTxInput(TX_LINE_IN);
@ -221,7 +218,7 @@ void setRigMode(RigMode m)
// dspMenu = &ssbMenu;
break;
case MODE_DIGI:
case RIG_MODE_DIGI:
// Digi sets the TX audio input to USB-in. Keying in this case must
// be via CAT control. Digital modes can also be used through the
// line-in, but the rig mode should be set to SSB in that case, and
@ -234,7 +231,7 @@ void setRigMode(RigMode m)
// dspMenu = &digiMenu;
break;
case MODE_CW:
case RIG_MODE_CW:
// CW just gets the radio off of Mic-In; but it won't use Line-In.
audioSelectTxInput(TX_LINE_IN);
audioCWFilter();
@ -245,6 +242,8 @@ void setRigMode(RigMode m)
//======================================================================
//elapsedMillis frame10hz = 0;
void setup() {
// put your setup code here, to run once:
initCAT(38400, SERIAL_8N1);
@ -261,19 +260,23 @@ void setup() {
audioInit();
#if defined(FACTORY_CALIBRATION)
setRigMode(MODE_TEST);
setRigMode(RIG_MODE_TEST);
#else
setRigMode(MODE_SSB);
setRigMode(RIG_MODE_SSB);
#endif
//frame10Hz = 0;
}
//======================================================================
void loop() {
elapsedMillis elapsed = 0;
// elapsedMillis elapsed = 0;
RigMode oldRigMode = rigMode;
RxFilter oldRxFilter = rxFilter;
switch(rigMode) {
case MODE_CW:
case RIG_MODE_CW:
if (keyer.do_paddles()) {
if (keyer.is_down()) {
digitalWrite(PTT_KEY_OUT_PIN, LOW);
@ -293,6 +296,28 @@ void loop() {
serviceCAT();
}
// send current status @ 10 Hz
//if (frame10Hz > 100) {
if ((rigMode != oldRigMode) || (rxFilter != oldRxFilter)) {
switch(rigMode) {
case RIG_MODE_SSB:
sendIOPSSBStatus(iopConfig.ssb);
break;
case RIG_MODE_DIGI:
sendIOPDigiStatus(iopConfig.digi);
break;
case RIG_MODE_CW:
sendIOPCWStatus(iopConfig.cw);
break;
case RIG_MODE_TEST:
sendIOPTestStatus();
}
//frame10Hz = 0;
}
//dspMenu->update();
/*