28cbb0363f
variables. No update functions currently. No indication that you're in the "edit" mode for a given variable.
270 lines
7.2 KiB
C++
270 lines
7.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};
|
|
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_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->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
|
|
//======================================================================
|