ubitx-iop/ubitx_iop/ubitx_iop.ino
Rob French 0a8e91c4a7 Revamped the fledgling menu system using the Embedded Template Library.
It works!

Started building up configuration menus.  Compiles, haven't tested yet.
Still learning about how to use the ETL/STL.
2020-06-11 23:50:50 -05:00

267 lines
7.3 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;
Main_menu main_menu(rig);
Menu_item* menu_item = &main_menu;
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;
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 update_io_menu(Menu_item* item, bool is_active)
{
Menu_string text;
if (!is_active || (is_active && item == nullptr)) {
sendIOPMenuInactive();
} else {
item->get_text(text);
sendIOPMenuDisplay(text.data());
}
}
//======================================================================
void loop()
{
static bool menu_is_active = false;
static bool menu_updated = false;
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();
menu_updated = false;
btn.update();
knobPos = knob.read();
if (btn.fell()) {
btnMillis = 0;
USBDEBUG("button pressed");
// cancel out any knob rotation that occurred during in conjunction with press/release
knob.write(0);
} else if (btn.rose() && menu_is_active) {
menu_updated = true;
if (btnMillis > 1000) {
// long press - exit
menu_item = menu_item->exit();
USBDEBUG("button released - long (exit)");
} else if (btnMillis > 500) {
// medium press - altSelect
menu_item = menu_item->altSelect();
USBDEBUG("button released - medium (altSelect)");
} else {
// short press - select
menu_item = menu_item->select();
USBDEBUG("button released - short (select)");
}
// cancel out any knob rotation that occurred during in conjunction with press/release
knob.write(0);
} else if (btn.rose() && !menu_is_active) {
menu_is_active = true;
menu_updated = true;
// cancel out any knob rotation that occurred during in conjunction with press/release
knob.write(0);
USBDEBUG("button released - main menu activated");
} else if (knobPos > 3 && menu_is_active) {
// left
menu_item->prev();
knob.write(0);
menu_updated = true;
USBDEBUG("knob turned left");
} else if (knobPos < -3 && menu_is_active) {
// right
menu_item->next();
knob.write(0);
menu_updated = true;
USBDEBUG("knob turned right");
}
if (menu_item == nullptr) {
menu_item = &main_menu;
menu_is_active = false;
menu_updated = true;
USBDEBUG("null menu - reset to main menu");
}
if (menu_updated) {
update_io_menu(menu_item, menu_is_active);
USBDEBUG("updated main menu");
}
// update the speech compressor. Really should do this elsewhere.
if (speechCompressor.isEnabled())
speechCompressor.update();
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
//======================================================================