ubitx-iop/iopcomm/iopcomm.h
Rob French 9c1a490963 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.
2020-05-18 08:16:54 -05:00

235 lines
5.4 KiB
C++

//======================================================================
// iopcomm.h
//======================================================================
#ifndef __iopcomm_h__
#define __iopcomm_h__
#include <stdint.h>
/* Message prefixes, starting with the ACK message (0). Message format
* consists of 1 or more bytes, where:
* b[0] - leftmost 3 bits == prefix
* - rightmost 5 bits == length of data (0-31)
* b[1]...b[31] (if present) - data bits
*/
enum PrefixID {
ACK = 0,
CAT_PREFIX,
IOP_PREFIX,
RAD_EEPROM_READ_PREFIX,
RAD_EEPROM_WRITE_PREFIX,
IOP_EEPROM_READ_PREFIX,
IOP_EEPROM_WRITE_PREFIX,
NUM_PREFIX_IDS
};
/* Masks for the leftmost 3 bits (prefix) and rightmost 5 bits (length)
* of a message.
*/
#define PREFIX_MASK 0xE0
#define LENGTH_MASK 0x1F
/* Convert a prefix and length to a byte, by shifting the prefix left
* 5 bits and OR-ing with the 5 bits of length.
*/
inline uint8_t prefixAndLengthToByte(PrefixID id, uint8_t len)
{
return (uint8_t(id) << 5) | (len & LENGTH_MASK);
}
/* Extract the prefix (leftmost 3 bits) from a byte.
*/
inline PrefixID byteToPrefix(uint8_t b)
{
return PrefixID(b >> 5);
}
/* Extract the length (rightmost 5 bits) from a byte.
*/
inline uint8_t byteToLength(byte b)
{
return uint8_t(b & LENGTH_MASK);
}
/* Message IDs/types, for IOP messages (messages between the Raduino and
* the IOP, not including CAT messages to be passed through).
*/
enum MessageID {
// Commands
IOP_MODE_COMMAND = 0,
IOP_START_TX_COMMAND,
IOP_STOP_TX_COMMAND,
IOP_CW_CONFIG_MSG,
// 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
};
/* Max length of an IOP message payload (data), based on the following
* message format:
*
* byte 0: prefix (3 bits) + length (5 bits)
* byte 1: message ID (type)
* bytes 2-31: data bytes
*/
#define IOP_MESSAGE_MAX_LEN 30
/* Rig modes. Currently just defined as what the IOP cares about, but
* maybe these need to be expanded to encompass all of the rig modes.
* (e.g. USB, LSB, etc.)
*/
enum RigMode {
RIG_MODE_SSB = 0,
RIG_MODE_DIGI,
RIG_MODE_CW,
RIG_MODE_TEST,
// add any new elements here
NUM_RIG_MODES
};
/* Keyer modes.
*/
enum KeyerMode {
KEYER_MODE_STRAIGHT = 0,
KEYER_MODE_IAMBIC_A,
KEYER_MODE_IAMBIC_B,
//KEYER_ULTIMATIC,
//KEYER_BUG,
// add any new elements here
NUM_KEYER_MODES
};
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;
struct IOPMessage {
uint8_t id;
uint8_t len;
uint8_t data[IOP_MESSAGE_MAX_LEN];
};
//======================================================================
// SSB CONFIGURATION
//======================================================================
struct SSBConfig {
// parameters
RxFilter filter = RX_FILTER_NORMAL;
};
//======================================================================
// DIGI CONFIGURATION
//======================================================================
struct DigiConfig {
// parameters
RxFilter filter = RX_FILTER_NORMAL;
};
//======================================================================
// CW CONFIGURATION
//======================================================================
struct CWConfig {
// 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
//======================================================================
/*
class Translator
{
public:
Translator(RigMode&, CWConfig&, Stream&);
void registerPrefixCb(PrefixID id, void (*func)(void*));
void registerMessageCb(MessageID id, void (*func)(void*));
void sendACK();
void sendIOPMessage(IOPMessage const&);
void receive();
void pack_ModeCommand(IOPMessage&, RigMode);
void pack_CWConfig(IOPMessage&, CWConfig const&);
void pack_ModeRequest(IOPMessage&);
void unpack(IOPMessage const&);
protected:
void unpack_ModeCommand(IOPMessage const&);
void unpack_CWConfig(IOPMessage const&);
void unpack_ModeRequest(IOPMessage const&);
private:
RigMode& mode;
CWConfig& cwConfig;
Stream& serial;
void (*prefixCb[NUM_PREFIX_IDS])(void*);
void (*messageCb[NUM_MESSAGE_IDS])(void*);
};
*/
#endif
//======================================================================
// EOF
//======================================================================