ubitx-v5d-xcvr/ubitx_iop/ubitx_iop.ino

319 lines
8.4 KiB
C++

//======================================================================
// ubitx_iop.ino
//======================================================================
#include <iopcomm.h>
#include "ubitx_iop.h"
#include <Bounce2.h>
#define BOUNCE_WITH_PROMPT_DETECTION
RigMode rigMode = MODE_SSB;
IOPConfig iopConfig;
#define MIC_PTT_PIN 21
#define LINE_PTT_PIN 20
#define PTT_KEY_OUT_PIN 2
Bounce micPTT = Bounce();
Bounce linePTT = Bounce();
TxState txState = TX_OFF;
Keyer keyer(15, 3.0); // need to make configurable
//SSBMenu ssbMenu();
//DigiMenu digiMenu();
//CWMenu cwMenu();
//MenuItem* dspMenu = &ssbMenu;
//======================================================================
// catPTTOn()
//
// NOTE: Should probably move this to cat.ino.
//======================================================================
void catPTTOn()
{
// Check if we're already transmitting. If so, then this command
// does nothing: existing transmission, from existing source and PTT,
// will continue.
if (txState != TX_OFF) return;
switch(rigMode) {
// 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:
//break;
case MODE_SSB:
// In SSB mode, CAT-PTT will always (de-)activate the Line-In TX
// audio source.
txState = TX_CAT;
audioSelectTxInput(TX_LINE_IN); // in case Mic-In is selected
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_DIGI:
// In Digital (USB) mode, CAT-PTT will always (de-)activate the
// USB-In TX audio source.
txState = TX_CAT;
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
}
}
//======================================================================
// catPTTOff()
//
// NOTE: Should probably move this to cat.ino.
//======================================================================
void catPTTOff()
{
// If we're not transmitting, or the active PTT is not CAT, then this
// command does nothing: CAT cannot interrupt other transmissions.
if (txState != TX_CAT) return;
switch(rigMode) {
// 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:
//break;
case MODE_SSB:
// In SSB mode, CAT-PTT will always (de-)activate the Line-In TX
// audio source.
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
audioReceive();
txState = TX_OFF;
break;
case MODE_DIGI:
// In Digital (USB) mode, CAT-PTT will always (de-)activate the
// USB-In TX audio source.
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
audioReceive();
txState = TX_OFF;
break;
}
}
//======================================================================
// checkMicPTT()
//======================================================================
void checkMicPTT()
{
micPTT.update();
// If we're transmitting, then we're just going to check if Mic-PTT
// 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
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();
txState = TX_OFF;
return;
}
if ((txState == TX_OFF) && micPTT.fell()) {
#if defined(DEBUG)
USBSERIAL.println("DEBUG: mic PTT depressed");
#endif
switch(rigMode) {
case MODE_CW:
txState = TX_MIC;
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_SSB:
txState = TX_MIC;
audioSelectTxInput(TX_MIC_IN);
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_DIGI:
// Mic PTT actuation during Digital does nothing.
break;
case MODE_TEST:
txState = TX_MIC;
audioSelectTxInput(TX_TEST_IN);
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
}
}
}
//======================================================================
// checkLinePTT()
//======================================================================
void checkLinePTT()
{
linePTT.update();
// If we're transmitting, then we're just going to check if Line-PTT
// was released--the Line-PTT can always be used to terminate a
// transmission from another source.
if ((txState != TX_OFF) && linePTT.rose()) {
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();
txState = TX_OFF;
return;
}
if ((txState == TX_OFF) && linePTT.fell()) {
switch(rigMode) {
case MODE_CW:
txState = TX_LINE;
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_SSB:
txState = TX_LINE;
audioSelectTxInput(TX_LINE_IN);
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_DIGI:
// Line PTT actuation during Digital does nothing.
break;
case MODE_TEST:
txState = TX_LINE;
audioSelectTxInput(TX_TEST_IN);
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
}
}
}
//======================================================================
void setRigMode(RigMode m)
{
rigMode = m;
switch(rigMode) {
case MODE_SSB:
case 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);
audioSSBFilter();
// dspMenu = &ssbMenu;
break;
case 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
// the rig could be keyed either via the line-in PTT, or via CAT.
// Digimodes could also be used through the mic-in, but in that case,
// the mic PTT line would need to be keyed by the computer rather
// than using CAT for PTT control.
audioSelectTxInput(TX_USB_IN);
audioDigiFilter();
// dspMenu = &digiMenu;
break;
case MODE_CW:
// CW just gets the radio off of Mic-In; but it won't use Line-In.
audioSelectTxInput(TX_LINE_IN);
audioCWFilter();
// dspMenu = &cwMenu;
break;
}
}
//======================================================================
void setup() {
// put your setup code here, to run once:
initCAT(38400, SERIAL_8N1);
AudioMemory(12);
micPTT.attach(MIC_PTT_PIN, INPUT_PULLUP);
micPTT.interval(25);
linePTT.attach(LINE_PTT_PIN, INPUT_PULLUP);
linePTT.interval(25);
pinMode(PTT_KEY_OUT_PIN, OUTPUT);
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
audioInit();
#if defined(FACTORY_CALIBRATION)
setRigMode(MODE_TEST);
#else
setRigMode(MODE_SSB);
#endif
}
//======================================================================
void loop() {
elapsedMillis elapsed = 0;
switch(rigMode) {
case MODE_CW:
if (keyer.do_paddles()) {
if (keyer.is_down()) {
digitalWrite(PTT_KEY_OUT_PIN, LOW);
} else {
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
}
// No break... if the paddle is not active, I want this to fall
// through to checkMicPTT etc... but return early if the paddle is
// active, to maximize responsiveness. Probably could just use
// 'if' statements here instead of the 'switch'.
return;
}
default:
checkMicPTT();
checkLinePTT();
serviceCAT();
}
//dspMenu->update();
/*
#if defined(DEBUG)
int frame_skews = 0; // for debugging; see how often we skew frames
#endif
// put your main code here, to run repeatedly:
// Run at a nominal 20 Hz frame rate.
#if defined(DEBUG)
if (frame_timer > 50) {
frame_skews += 1;
}
#endif
while (frame_timer < 50) { // this doesn't seem like a good way to do this
}
*/
}
//======================================================================
// EOF
//======================================================================