c27e2eddd6
displayed on the Raduino. See most recently Raduino (ubitx-v5d) commit.
290 lines
7.6 KiB
C++
290 lines
7.6 KiB
C++
//======================================================================
|
|
// ubitx_iop.ino
|
|
//======================================================================
|
|
|
|
#include <Encoder.h>
|
|
#include <iopcomm.h>
|
|
#include "audio.h"
|
|
#include "config.h"
|
|
#include "ubitx_iop.h"
|
|
#include "keyer.h"
|
|
#include "menu.h"
|
|
#include "rig.h"
|
|
#include "TxSwitch.h"
|
|
|
|
Keyer keyer{15, 3.0}; // NOTE: make configurable
|
|
|
|
RigConfig rigConfig;
|
|
RigAudio rigAudio{rigConfig.audio};
|
|
Rig rig{rigConfig, rigAudio};
|
|
|
|
BPFilter rxFilter{300, 3100, false};
|
|
|
|
SSBMode lsbMode{rigConfig.lsb, rigAudio, rxFilter};
|
|
SSBMode usbMode{rigConfig.usb, rigAudio, rxFilter};
|
|
CWMode cwlMode{rigConfig.cwl, rigAudio, rxFilter};
|
|
CWMode cwuMode{rigConfig.cwu, rigAudio, rxFilter};
|
|
DGTMode dglMode{rigConfig.dgl, rigAudio, rxFilter};
|
|
DGTMode dguMode{rigConfig.dgu, rigAudio, rxFilter};
|
|
TTMode ttlMode{rigConfig.ttl, rigAudio, rxFilter};
|
|
TTMode ttuMode{rigConfig.ttu, rigAudio, rxFilter};
|
|
|
|
CATSwitch catPTT;
|
|
//MicSwitch micPTTHelper;
|
|
GPIOSwitch micPTT(true, MIC_PTT_PIN);
|
|
//LineSwitch linePTTHelper;
|
|
GPIOSwitch linePTT(false, LINE_PTT_PIN);
|
|
|
|
Encoder knob(ENCODER_A_PIN, ENCODER_B_PIN);
|
|
long knobPos = 0;
|
|
|
|
Bounce btn;
|
|
elapsedMillis btnMillis;
|
|
|
|
TopMenu topMenu(rig);
|
|
MenuItem* menu = &topMenu;
|
|
|
|
elapsedMillis menuUpdateMillis;
|
|
elapsedMillis frameMillis;
|
|
unsigned frameTime;
|
|
unsigned frameCounter;
|
|
unsigned audioProcUsage;
|
|
unsigned audioMemUsage;
|
|
|
|
//======================================================================
|
|
|
|
void setup() {
|
|
// put your setup code here, to run once:
|
|
initCAT(38400, SERIAL_8N1);
|
|
USBDEBUG("setup started");
|
|
|
|
AudioMemory(16); // NOTE: Need to fine tune this. Have had errors due to this being too low.
|
|
|
|
// initialize the filter(s)
|
|
rxFilter.init();
|
|
|
|
// adding all of the modes to the rig
|
|
rig.addNewMode(RIG_MODE_LSB, &lsbMode);
|
|
rig.addNewMode(RIG_MODE_USB, &usbMode);
|
|
rig.addNewMode(RIG_MODE_CWL, &cwlMode);
|
|
rig.addNewMode(RIG_MODE_CWU, &cwuMode);
|
|
rig.addNewMode(RIG_MODE_DGL, &dglMode);
|
|
rig.addNewMode(RIG_MODE_DGU, &dguMode);
|
|
rig.addNewMode(RIG_MODE_TTL, &ttlMode);
|
|
rig.addNewMode(RIG_MODE_TTU, &ttuMode);
|
|
|
|
initKeyLine();
|
|
rigAudio.init();
|
|
|
|
frameCounter = 0;
|
|
frameMillis = 0;
|
|
|
|
menuUpdateMillis = 0;
|
|
|
|
knob.write(0);
|
|
|
|
btn.attach(ENCODER_SW_PIN, INPUT_PULLUP);
|
|
btn.interval(25);
|
|
|
|
rig.init();
|
|
|
|
USBDEBUG("setup completed");
|
|
// audioInit();
|
|
/*
|
|
#if defined(FACTORY_CALIBRATION)
|
|
setRigMode(RIG_MODE_TEST);
|
|
#else
|
|
setRigMode(RIG_MODE_SSB);
|
|
#endif
|
|
*/
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
void loop()
|
|
{
|
|
static char frame_status[100];
|
|
static char old_mode_text[17] = " ";
|
|
static bool paddle_loop = false;
|
|
// long oldPos = knobPos;
|
|
|
|
RigMode oldRigMode;
|
|
|
|
frameCounter++;
|
|
|
|
if (rig.isCWMode()) {
|
|
if (keyer.do_paddles()) {
|
|
|
|
// Checking for T/R separately from the paddle loop, because it's
|
|
// possible we're already transmitting (PTT/Key being held), and
|
|
// we don't want to run the tx() actions if we're already in TX.
|
|
if (rig.isRx()) {
|
|
USBDEBUG("entered TX via paddles");
|
|
rig.tx();
|
|
}
|
|
|
|
paddle_loop = true;
|
|
|
|
if (keyer.is_down()) {
|
|
setKeyDown();
|
|
} else {
|
|
setKeyUp();
|
|
}
|
|
|
|
return; // return early for paddle responsiveness
|
|
} else {
|
|
if (paddle_loop) {
|
|
// If we exit the paddle loop (i.e. keyer completes its keying
|
|
// sequence), then we'll go back to receive, even if one of the
|
|
// PTT/Key lines is still held separately. General principle is
|
|
// that if "something" stops transmitting, then the rig will
|
|
// stop transmitting.
|
|
paddle_loop = false;
|
|
rig.rx();
|
|
USBDEBUG("exited TX from paddles");
|
|
}
|
|
}
|
|
}
|
|
|
|
rig.update();
|
|
|
|
oldRigMode = rig.modeNum();
|
|
|
|
// Update the mic PTT. We need to tell it if we're in SSB mode, so that
|
|
// it knows if it should switch to the mic input if pressed. We also
|
|
// need to make it inactive if we're in DGT mode, since only CAT will be
|
|
// used to start transmitting in that case.
|
|
micPTT.setSSBMode(rig.isSSBMode());
|
|
micPTT.update(rig.mode(), !rig.isDGTMode());
|
|
|
|
// Update the line PTT. We need to tell it if we're in SSB mode, so that
|
|
// it knows if it should switch to the line input if pressed. We also
|
|
// need to make it inactive if we're in DGT mode, since only CAT will be
|
|
// used to start transmitting in that case.
|
|
linePTT.setSSBMode(rig.isSSBMode());
|
|
linePTT.update(rig.mode(), !rig.isDGTMode());
|
|
|
|
serviceCAT();
|
|
|
|
/*
|
|
// send current status @ 10 Hz
|
|
//if (frame10Hz > 100) {
|
|
if ((rig.modeNum() != oldRigMode)) { // || (rxFilter != oldRxFilter)) {
|
|
USBDEBUG("mode changed");
|
|
switch(rig.modeNum()) {
|
|
case RIG_MODE_LSB:
|
|
USBDEBUG("sending LSB mode status");
|
|
sendIOPSSBStatus(rigConfig.lsb);
|
|
break;
|
|
|
|
case RIG_MODE_USB:
|
|
USBDEBUG("sending USB mode status");
|
|
sendIOPSSBStatus(rigConfig.usb);
|
|
break;
|
|
|
|
case RIG_MODE_DGL:
|
|
USBDEBUG("sending DGL mode status");
|
|
sendIOPDGTStatus(rigConfig.dgl);
|
|
break;
|
|
|
|
case RIG_MODE_DGU:
|
|
USBDEBUG("sending DGU mode status");
|
|
sendIOPDGTStatus(rigConfig.dgu);
|
|
break;
|
|
|
|
case RIG_MODE_CWL:
|
|
USBDEBUG("sending CWL mode status");
|
|
sendIOPCWStatus(rigConfig.cwl);
|
|
break;
|
|
|
|
case RIG_MODE_CWU:
|
|
USBDEBUG("sending CWU mode status");
|
|
sendIOPCWStatus(rigConfig.cwu);
|
|
break;
|
|
|
|
case RIG_MODE_TTL:
|
|
USBDEBUG("sending TTL mode status");
|
|
sendIOPTestStatus();
|
|
break;
|
|
|
|
case RIG_MODE_TTU:
|
|
USBDEBUG("sending TTU mode status");
|
|
sendIOPTestStatus();
|
|
break;
|
|
}
|
|
//frame10Hz = 0;
|
|
}
|
|
*/
|
|
btn.update();
|
|
if (btn.fell()) {
|
|
//sendIOPMenuDisplay("PRESSED ", 2);
|
|
btnMillis = 0;
|
|
USBDEBUG("button pressed");
|
|
} else if (btn.rose()) {
|
|
if (btnMillis > 1000) {
|
|
// long press - exit
|
|
//sendIOPMenuDisplay("REL-LONG ", 2);
|
|
menu->exit();
|
|
USBDEBUG("button released - long (exit)");
|
|
} if (btnMillis > 500) {
|
|
// medium press - altSelect
|
|
menu->altSelect();
|
|
USBDEBUG("button released - medium (altSelect)");
|
|
} else {
|
|
// short press - select
|
|
//sendIOPMenuDisplay("REL-SHORT ", 2);
|
|
menu->select();
|
|
USBDEBUG("button released - short (select)");
|
|
}
|
|
// menu->update();
|
|
}
|
|
|
|
knobPos = knob.read();
|
|
// wait til we turn greater than 3 pos in either direction, for "debouncing"
|
|
|
|
if (knobPos > 3) {
|
|
// left
|
|
//sendIOPMenuDisplay("LEFT ", 5);
|
|
menu->prev();
|
|
// menu->update();
|
|
knob.write(0);
|
|
USBDEBUG("knob turned left");
|
|
} else if (knobPos < -3) {
|
|
// right
|
|
//sendIOPMenuDisplay("RIGHT ", 5);
|
|
menu->next();
|
|
// menu->update();
|
|
knob.write(0);
|
|
USBDEBUG("knob turned right");
|
|
}
|
|
|
|
// if (strcmp(old_mode_text, rig.modeText())) {
|
|
// menu->update();
|
|
// strcpy(old_mode_text, rig.modeText());
|
|
// }
|
|
|
|
// update the menu at a 10 Hz rate
|
|
if (menuUpdateMillis > 100) {
|
|
menu->update();
|
|
menuUpdateMillis = 0;
|
|
}
|
|
|
|
if (frameMillis > 5000) {
|
|
#if defined(DEBUG)
|
|
frameTime = frameMillis;
|
|
audioProcUsage = AudioProcessorUsageMax();
|
|
audioMemUsage = AudioMemoryUsageMax();
|
|
sprintf(frame_status, "update: %u ms, %u frames, %d %% CPU max, %d %% mem max\n", frameTime, frameCounter, audioProcUsage, audioMemUsage);
|
|
USBDEBUG(frame_status);
|
|
#endif
|
|
frameMillis = 0;
|
|
frameCounter = 0;
|
|
}
|
|
|
|
//audioUpdate(); // was used to update the speech compressor
|
|
}
|
|
|
|
//======================================================================
|
|
// EOF
|
|
//======================================================================
|