kill my Teensy 3.2. I unplugged the Teensy-to-Raduino comm lines in order to program the Raduino. When I plugged them back in, I didn't realize that I was off by one pin. So I believe something that should've only gotten 3.3V, got more. No light on the Teensy. This development effort, while it has been fruitful, is definitely complicated. I don't think I have the bandwidth to continue it. I plan on merging all the branches back to master, collecting the pieces-parts of uBITX V5D, and calling it "done". I will rebuild my uBITX V5 back into a relatively stock configuration, and use an external digital interface (see KK5JY).
		
			
				
	
	
		
			473 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			473 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//======================================================================
 | 
						|
// iopcomm.cpp
 | 
						|
//======================================================================
 | 
						|
 | 
						|
#include <Arduino.h>
 | 
						|
 | 
						|
#include "iopcomm.h"
 | 
						|
 | 
						|
#if defined(TEENSYDUINO)
 | 
						|
	// Compiling for the Teensy, so assuming this is IOP code.
 | 
						|
	#define MYSERIAL Serial1
 | 
						|
#else
 | 
						|
	// Not compiling for the Teensy, so assuming this is Raduino code.
 | 
						|
	#define MYSERIAL Serial
 | 
						|
#endif
 | 
						|
 | 
						|
//======================================================================
 | 
						|
 | 
						|
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));
 | 
						|
	MYSERIAL.write(msg.id);
 | 
						|
	for (int i = 0; i < msg.len; i++) {
 | 
						|
		MYSERIAL.write(msg.data[i]);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
//======================================================================
 | 
						|
 | 
						|
void recvIOPMessage(IOPMessage& msg, const uint8_t* buf, int len)
 | 
						|
{	
 | 
						|
	msg.id = buf[0];
 | 
						|
	msg.len = len - 1;
 | 
						|
	for (int i = 1; i < len; i++) {
 | 
						|
		msg.data[i-1] = buf[i];
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
//======================================================================
 | 
						|
 | 
						|
void sendIOPModeCommand(rig_mode mode)
 | 
						|
{
 | 
						|
	IOPMessage m;
 | 
						|
	m.id = IOP_MODE_COMMAND;
 | 
						|
	m.len = 1;
 | 
						|
	m.data[0] = static_cast<uint8_t>(mode);
 | 
						|
	sendIOPMessage(m);
 | 
						|
}
 | 
						|
 | 
						|
//======================================================================
 | 
						|
 | 
						|
void sendIOPStartTxCommand()
 | 
						|
{
 | 
						|
	IOPMessage m;
 | 
						|
	m.id = IOP_START_TX_COMMAND;
 | 
						|
	m.len = 0;
 | 
						|
	sendIOPMessage(m);
 | 
						|
}
 | 
						|
 | 
						|
//======================================================================
 | 
						|
 | 
						|
void sendIOPStopTxCommand()
 | 
						|
{
 | 
						|
	IOPMessage m;
 | 
						|
	m.id = IOP_STOP_TX_COMMAND;
 | 
						|
	m.len = 0;
 | 
						|
	sendIOPMessage(m);
 | 
						|
}
 | 
						|
 | 
						|
//======================================================================
 | 
						|
 | 
						|
void sendIOPModeRequest()
 | 
						|
{
 | 
						|
	IOPMessage m;
 | 
						|
	m.id = IOP_MODE_REQUEST;
 | 
						|
	m.len = 4;	// NOTE: LEN = 4 for padding only... temporary
 | 
						|
	sendIOPMessage(m);
 | 
						|
}
 | 
						|
 | 
						|
//======================================================================
 | 
						|
 | 
						|
void sendIOPDebugMessage(const char* text)
 | 
						|
{
 | 
						|
	IOPMessage m;
 | 
						|
	m.id = IOP_DEBUG_MSG;
 | 
						|
	m.len = strlen(text);
 | 
						|
	if (m.len > IOP_MESSAGE_MAX_LEN) {
 | 
						|
		m.len = IOP_MESSAGE_MAX_LEN;
 | 
						|
	}
 | 
						|
	strncpy(m.data, text, m.len);
 | 
						|
	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);
 | 
						|
//}
 | 
						|
 | 
						|
////======================================================================
 | 
						|
//// DGT STATUS MESSAGE
 | 
						|
////======================================================================
 | 
						|
 | 
						|
//void sendIOPDGTStatus(DGTConfig const &c)
 | 
						|
//{
 | 
						|
	//IOPMessage m;
 | 
						|
	//m.id = IOP_DGT_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);
 | 
						|
//}
 | 
						|
 | 
						|
//======================================================================
 | 
						|
// MENU DISPLAY MESSAGE
 | 
						|
//======================================================================
 | 
						|
 | 
						|
void sendIOPMenuDisplay(const char* text)
 | 
						|
{
 | 
						|
	IOPMessage m;
 | 
						|
	int l = strlen(text);
 | 
						|
	m.id = IOP_MENU_DISPLAY_MSG;
 | 
						|
	m.len = 16;
 | 
						|
	for (int i = 0; i < 16; i++) {
 | 
						|
		if (i < l) {
 | 
						|
			m.data[i] = text[i];
 | 
						|
		} else {
 | 
						|
			m.data[i] = ' ';
 | 
						|
		}
 | 
						|
	}
 | 
						|
	m.data[16] = '\0';
 | 
						|
	sendIOPMessage(m);
 | 
						|
}
 | 
						|
 | 
						|
//======================================================================
 | 
						|
// MENU INACTIVE MESSAGE
 | 
						|
//======================================================================
 | 
						|
 | 
						|
void sendIOPMenuInactive()
 | 
						|
{
 | 
						|
	IOPMessage m;
 | 
						|
	m.id = IOP_MENU_INACTIVE_MSG;
 | 
						|
	m.len = 4;	// NOTE: LEN = 4 for padding only... temporary
 | 
						|
	sendIOPMessage(m);
 | 
						|
}
 | 
						|
 | 
						|
//======================================================================
 | 
						|
 | 
						|
/*
 | 
						|
enum SerialState {
 | 
						|
  NORMAL = 0,
 | 
						|
  CAT_MODE,
 | 
						|
  IOP_MODE,
 | 
						|
  EEPROM_READ,
 | 
						|
  EEPROM_WRITE,
 | 
						|
};
 | 
						|
 | 
						|
Translator::Translator(RigMode& m, CWConfig& c, Stream& s = SERIAL):
 | 
						|
mode(m), cwConfig(c), serial(s)
 | 
						|
{
 | 
						|
	for (int i = 0; i < NUM_PREFIX_IDS; i++) {
 | 
						|
		prefixCb[i] = NULL;
 | 
						|
	}
 | 
						|
	
 | 
						|
	for (int i = 0; i < NUM_MESSAGE_IDS; i++) {
 | 
						|
		messageCb[i] = NULL;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Translator::sendACK()
 | 
						|
{
 | 
						|
	serial.write(prefixAndLengthToByte(ACK, 0));
 | 
						|
}
 | 
						|
 | 
						|
void Translator::sendCATMessage(byte b, bool continued=false)
 | 
						|
{
 | 
						|
	if (!continued) {	// we're starting a CAT transmission sequence
 | 
						|
				
 | 
						|
	} else {			// we're continuing a CAT transmission sequence
 | 
						|
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Translator::sendIOPMessage(IOPMessage const& m)
 | 
						|
{	
 | 
						|
	serial.write(prefixAndLengthToByte(IOP_PREFIX, m.len+1));
 | 
						|
	serial.write(m.id);
 | 
						|
	for (int i = 0; i < m.len; i++) {
 | 
						|
		serial.write(m.data[i]);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void Translator::receive()
 | 
						|
{
 | 
						|
	static SerialState state;
 | 
						|
	
 | 
						|
	static PrefixID readPrefix = 0;
 | 
						|
	static uint8_t  readLength = 0;
 | 
						|
 | 
						|
	static IOPMessage iopMsg;
 | 
						|
 | 
						|
	static uint8_t cmdLength = 0;
 | 
						|
	static byte    cmdBuffer[16]; 
 | 
						|
	static char    cmdString[17]; // added a char for null termination when required
 | 
						|
 | 
						|
	static uint16_t eepromStartIndex;
 | 
						|
	static uint16_t eepromReadLength;
 | 
						|
	static int      eepromMagicFlag = 0;
 | 
						|
 | 
						|
	int incomingByte;
 | 
						|
	
 | 
						|
	for (int i = 0; i < serial.available(); i++) {
 | 
						|
		incomingByte = serial.read();
 | 
						|
 | 
						|
		switch(state) {
 | 
						|
			case NORMAL:
 | 
						|
			if (incomingByte == ACK) {
 | 
						|
				prefixCb[ACK](NULL);
 | 
						|
			} else {
 | 
						|
				readPrefix = byteToPrefix(incomingbyte);
 | 
						|
				readLength = byteToLength(incomingbyte);
 | 
						|
				if (readLength > 0) {
 | 
						|
					switch(readPrefix) {
 | 
						|
						case CAT_PREFIX:
 | 
						|
						case RAD_EEPROM_WRITE_PREFIX:
 | 
						|
						state = CAT_MODE;
 | 
						|
						break;
 | 
						|
	  
 | 
						|
						case IOP_PREFIX:
 | 
						|
						state = IOP_MODE;
 | 
						|
						iopMsg.len = readLength - 1;
 | 
						|
						cmdLength = 0;
 | 
						|
						break;
 | 
						|
	  
 | 
						|
						case RAD_EEPROM_READ_PREFIX:
 | 
						|
						state = EEPROM_READ;
 | 
						|
						readLength = 5;
 | 
						|
						eepromMagicFlag = 0;
 | 
						|
						break;
 | 
						|
 | 
						|
						default:
 | 
						|
						// should never happen
 | 
						|
						break;
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
			break;
 | 
						|
 | 
						|
			case CAT_MODE:
 | 
						|
			// In CAT mode, we just pass thru the remaining bytes to the PC.
 | 
						|
			if 
 | 
						|
			USBSERIAL.write(incomingByte);
 | 
						|
			readLength--;
 | 
						|
			if (readLength == 0) {
 | 
						|
				state = NORMAL;
 | 
						|
			}
 | 
						|
			break;
 | 
						|
 | 
						|
			case IOP_MODE:			
 | 
						|
			cmdBuffer[cmdLength] = incomingByte;
 | 
						|
			cmdLength++;
 | 
						|
			readLength--;
 | 
						|
			if (readLength == 0) {
 | 
						|
				processIOPCommand(cmdBuffer, cmdLength);
 | 
						|
				state = NORMAL;
 | 
						|
			}
 | 
						|
			break;
 | 
						|
 | 
						|
			case EEPROM_READ:
 | 
						|
			readLength--;
 | 
						|
			switch(readLength) {
 | 
						|
				case 4:
 | 
						|
				eepromStartIndex = incomingByte;
 | 
						|
				if (incomingByte == 0x16) {
 | 
						|
					magicFlag++;
 | 
						|
				}
 | 
						|
				break;
 | 
						|
			
 | 
						|
				case 3:
 | 
						|
				eepromStartIndex += (256 * incomingByte);
 | 
						|
				if (incomingByte == 0xe8) {
 | 
						|
					magicFlag++;
 | 
						|
				}
 | 
						|
				break;
 | 
						|
			
 | 
						|
				case 2:
 | 
						|
				eepromReadLength = incomingByte;
 | 
						|
				break;
 | 
						|
			
 | 
						|
				case 1:
 | 
						|
				eepromReadLength += (256 * incomingByte);
 | 
						|
				break;
 | 
						|
			
 | 
						|
				case 0:
 | 
						|
				USBSERIAL.write(incomingByte);
 | 
						|
				if (magicFlag == 2) {
 | 
						|
					readLength = 126 + 2;
 | 
						|
				} else {
 | 
						|
					readLength = eepromReadLength + 2;
 | 
						|
				}
 | 
						|
				state = CAT_MODE;
 | 
						|
				break;
 | 
						|
 | 
						|
				default:
 | 
						|
				// should never happen
 | 
						|
				break;
 | 
						|
		  }
 | 
						|
		  break;
 | 
						|
 | 
						|
		  case EEPROM_WRITE:
 | 
						|
		  // TODO
 | 
						|
		  break;
 | 
						|
 | 
						|
		  default:
 | 
						|
		  // should never happen...
 | 
						|
		  break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Translator::registerPrefixCb(PrefixID id, void (*func)(void*))
 | 
						|
{
 | 
						|
	if (id >= 0 && id < NUM_PREFIX_IDS) {
 | 
						|
		prefixCb[id] = func;
 | 
						|
	}
 | 
						|
 | 
						|
void Translator::registerMessageCb(MessageID id, void (*func)(void*))
 | 
						|
{
 | 
						|
	if (id >= 0 && id < NUM_MESSAGE_IDS) {
 | 
						|
		messageCb[id] = func;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Translator::pack_ModeCommand(IOPMessage& m, RigMode r)
 | 
						|
{
 | 
						|
	m.id = IOP_MODE_COMMAND;
 | 
						|
	m.len = 1;
 | 
						|
	m.data[0] = r;
 | 
						|
}
 | 
						|
 | 
						|
void Translator::unpack_ModeCommand(IOPMessage const& m)
 | 
						|
{
 | 
						|
	*mode = RigMode(m.data[0]);
 | 
						|
}
 | 
						|
 | 
						|
void Translator::pack_CWConfig(IOPMessage &m, CWConfig const& c)
 | 
						|
{
 | 
						|
	m.id  = IOP_CW_CONFIG_MSG;
 | 
						|
	m.len = 6;
 | 
						|
	// mode
 | 
						|
	m.data[0] = byte(c.mode);
 | 
						|
	// flags
 | 
						|
	m.data[1] = NO_FLAGS;
 | 
						|
	m.data[1] |= (c.reversed ? REVERSED : 0);
 | 
						|
	// parameters
 | 
						|
	m.data[2] = byte(c.wpm);
 | 
						|
	m.data[3] = byte(c.weight * 10.0);
 | 
						|
	m.data[4] = byte(c.sidetone >> 8);
 | 
						|
	m.data[5] = byte(c.sidetone | 0x0F);    
 | 
						|
}
 | 
						|
 | 
						|
void Translator::unpack_CWConfig(IOPMessage const &m)
 | 
						|
{
 | 
						|
	//if (m.id != IOP_CW_CONFIG_MSG || m.len != 6) {
 | 
						|
	//  // do some error thing...
 | 
						|
	//}
 | 
						|
	//mode 
 | 
						|
	cwConfig->mode  = KeyMode(m.data[0]);
 | 
						|
	// flags
 | 
						|
	cwConfig->reversed = bool(m.data[1] & REVERSED);
 | 
						|
	// parameters
 | 
						|
	cwConfig->wpm = uint8_t(m.data[2]);
 | 
						|
	cwConfig->weight = float(m.data[3]) / 10.0;
 | 
						|
	cwConfig->sidetone = (m.data[4] << 8) | m.data[5];
 | 
						|
}
 | 
						|
 | 
						|
void Translator::pack_ModeRequest(IOPMessage& m)
 | 
						|
{
 | 
						|
	m.id = IOP_MODE_REQUEST;
 | 
						|
	m.len = 0;
 | 
						|
}
 | 
						|
 | 
						|
void Translator::unpack_ModeRequest(IOPMessage const& m)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void Translator::unpack(IOPMessage const& m)
 | 
						|
{
 | 
						|
	switch (m.id) {
 | 
						|
		case IOP_MODE_COMMAND:
 | 
						|
		unpack_ModeCommand(m);
 | 
						|
		messageCb[m.id](mode);
 | 
						|
		break;
 | 
						|
		
 | 
						|
		case IOP_START_TX_COMMAND:
 | 
						|
		break;
 | 
						|
		
 | 
						|
		case IOP_STOP_TX_COMMAND:
 | 
						|
		break;
 | 
						|
		
 | 
						|
		case IOP_CW_CONFIG_MSG:
 | 
						|
		unpack_CWConfig(m);
 | 
						|
		messageCb[m.id](cwConfig);
 | 
						|
		break;			
 | 
						|
		
 | 
						|
		case IOP_MODE_REQUEST:
 | 
						|
		unpack_ModeRequest(m);
 | 
						|
		messageCb[m.id](NULL);
 | 
						|
		break;
 | 
						|
		
 | 
						|
		case IOP_CW_STATUS_MSG:
 | 
						|
		break;
 | 
						|
	}
 | 
						|
}
 | 
						|
*/
 | 
						|
//======================================================================
 | 
						|
// EOF
 | 
						|
//======================================================================
 |