ubitx-v5d-xcvr/ubitx_iop/ubitx_iop.ino

236 lines
6.2 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};
basic_rig rig{rigConfig, rigAudio};
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.
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");
}
//======================================================================
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;
rig_mode oldRigMode;
frameCounter++;
if (rig.is_cw_mode()) {
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.is_rx()) {
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.get_rig_mode();
// 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.is_ssb_mode());
micPTT.update(rig.mode(), !rig.is_digi_mode());
// 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.is_ssb_mode());
linePTT.update(rig.mode(), !rig.is_digi_mode());
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_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
if (menu_is_active) {
menu_item = menu_item->altSelect();
} else {
menu_item = audio_config_menu;
menu_is_active = true;
}
USBDEBUG("button released - medium (altSelect)");
} else {
// short press - select
if (menu_is_active) {
menu_item = menu_item->select();
} else {
menu_item = &main_menu;
menu_is_active = true;
}
USBDEBUG("button released - short (select)");
}
// cancel out any knob rotation that occurred during in conjunction with press/release
knob.write(0);
} else if (knobPos > 3 && menu_is_active) {
// left
menu_item = menu_item->prev();
knob.write(0);
menu_updated = true;
USBDEBUG("knob turned left");
} else if (knobPos < -3 && menu_is_active) {
// right
menu_item = 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");
}
rig.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
//======================================================================