Initial commit.

This commit is contained in:
Rob French 2020-10-29 18:08:42 -05:00
commit 8d88437702
6 changed files with 818 additions and 0 deletions

0
README.md Normal file
View File

20
digibox/cat_serial.h Normal file
View File

@ -0,0 +1,20 @@
//======================================================================
// cat_serial.h
//======================================================================
#ifndef __cat_serial_h__
#define __cat_serial_h__
namespace cat_serial
{
void init(cat_serial_cfg& c);
void update(int msec);
};
#endif
//======================================================================
// EOF
//======================================================================

368
digibox/dsp_audio.cpp Normal file
View File

@ -0,0 +1,368 @@
//======================================================================
// dsp_audio.cpp
//======================================================================
#include <dynamicFilters.h>
#include <effect_compressor_fb.h>
#include "dsp_audio.h"
#define RX_RIG_IN 0
#define RX_USB_IN 1
#define RX_ST_IN 2 // sidetone
#define TX_MIC_IN 0
#define TX_LINE_IN 0
#define TX_USB_IN 1
#define TX_TEST_IN 2
#define RX_BPF_ONLY 0
#define RX_NOTCH_ON 1
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
namespace dsp_audio
{
// GUItool: begin automatically generated code
AudioInputI2S line_in; //xy=148.9999771118164,131
AudioInputUSB usb_in; //xy=148.9999771118164,303
AudioSynthWaveformSine sidetone; //xy=150.9999771118164,214
AudioSynthWaveformSine sine2; //xy=337.9999771118164,482
AudioSynthWaveformSine sine1; //xy=338.9999771118164,428
AudioAnalyzeFFT256 rx_fft; //xy=370.0127944946289,103.02459716796875
AudioAnalyzeRMS rx_rms; //xy=376.9999771118164,20
AudioAnalyzePeak rx_peak; //xy=376.9999771118164,65
AudioEffectFade tx_comp; //xy=400.99999237060547,260.99999809265137
AudioAnalyzeRMS tx_comp_rms; //xy=402.9999771118164,224
AudioMixer4 rx_in_mix; //xy=458.9999771118164,163
AudioFilterFIR rx_fir_filter; //xy=628.0000839233398,135.00000476837158
AudioMixer4 tx_mix; //xy=666.9999771118164,321
AudioFilterBiquad rx_biquad_filter; //xy=765.7827301025391,183.02459716796875
AudioAnalyzeRMS tx_rms; //xy=855.9999771118164,449
AudioAnalyzePeak tx_peak; //xy=857.9999771118164,393
AudioAmplifier tx_line_out_cal; //xy=906.9999771118164,255
AudioAmplifier tx_usb_out_cal; //xy=907.9999771118164,312
AudioMixer4 rx_out_mix; //xy=933.78271484375,119.02459144592285
AudioAmplifier rx_usb_out_cal; //xy=1155,180.99999904632568
AudioAmplifier rx_line_out_cal; //xy=1156.9999771118164,109.00000381469727
AudioAmplifier rx_spkr_out_cal; //xy=1167.0000076293945,50
AudioOutputAnalog spkr_out; //xy=1307.000015258789,53
AudioOutputUSB usb_out; //xy=1332.999984741211,291.0000114440918
AudioOutputI2S line_out; //xy=1374.9999618530273,207.0000057220459
AudioConnection patchCord1(line_in, 0, rx_rms, 0);
AudioConnection patchCord2(line_in, 0, rx_peak, 0);
AudioConnection patchCord3(line_in, 0, rx_in_mix, 0);
AudioConnection patchCord4(line_in, 0, rx_fft, 0);
AudioConnection patchCord5(line_in, 1, tx_comp, 0);
AudioConnection patchCord6(line_in, 1, tx_comp_rms, 0);
AudioConnection patchCord7(usb_in, 0, rx_in_mix, 1);
AudioConnection patchCord8(usb_in, 1, tx_mix, 1);
AudioConnection patchCord9(sidetone, 0, rx_in_mix, 2);
AudioConnection patchCord10(sine2, 0, tx_mix, 3);
AudioConnection patchCord11(sine1, 0, tx_mix, 2);
AudioConnection patchCord12(tx_comp, 0, tx_mix, 0);
AudioConnection patchCord13(rx_in_mix, rx_fir_filter);
AudioConnection patchCord14(rx_fir_filter, rx_biquad_filter);
AudioConnection patchCord15(rx_fir_filter, 0, rx_out_mix, 0);
AudioConnection patchCord16(tx_mix, tx_line_out_cal);
AudioConnection patchCord17(tx_mix, tx_usb_out_cal);
AudioConnection patchCord18(tx_mix, tx_peak);
AudioConnection patchCord19(tx_mix, tx_rms);
AudioConnection patchCord20(rx_biquad_filter, 0, rx_out_mix, 1);
AudioConnection patchCord21(tx_line_out_cal, 0, line_out, 1);
AudioConnection patchCord22(tx_usb_out_cal, 0, usb_out, 1);
AudioConnection patchCord23(rx_out_mix, spkr_out_cal);
AudioConnection patchCord24(rx_out_mix, rx_line_out_cal);
AudioConnection patchCord25(rx_out_mix, rx_usb_out_cal);
AudioConnection patchCord26(rx_usb_out_cal, 0, usb_out, 0);
AudioConnection patchCord27(rx_line_out_cal, 0, line_out, 0);
AudioConnection patchCord28(spkr_out_cal, spkr_out);
AudioControlSGTL5000 audioCtrl; //xy=648,517
// GUItool: end automatically generated code
class configurator
{
public:
configurator(dsp_audio_cfg& c): data(c) {}
dsp_audio_cfg& data;
} *cfg = nullptr;
};
void dsp_audio::init(dsp_audio_cfg& c) {
USBDEBUG("audio initialization started");
if (cfg != nullptr) {
delete cfg;
}
cfg = new configurator(c);
audio_ctrl.enable();
audio_ctrl.adcHighPassFilterEnable(); // default
audio_ctrl.dacVolume(1.0); // default
audio_ctrl.dacVolumeRampDisable(); // not default; just trying to cull out culprits for my high freq hiss
audio_ctrl.audioProcessorDisable();
audio_ctrl.autoVolumeDisable();
audio_ctrl.surroundSoundDisable();
audio_ctrl.enhanceBassDisable();
audio_ctrl.eqSelect(FLAT_FREQUENCY); // eventually, use this to smooth out the normal uBITX passband
audio_ctrl.muteHeadphone(); // not using the headphone output
audio_ctrl.volume(0.0); // not using the headphone output
audio_ctrl.inputSelect(AUDIO_INPUT_LINEIN); // required for RX audio
audio_ctrl.unmuteLineout(); // required for RX audio
audio_ctrl.lineInLevel(cfg.data.rx_rig_in_level, cfg.data.tx_line_in_level); // NOTE: need to see if this persists through input changes (see mic gain...)
audio_ctrl.lineOutLevel(cfg.data.rx_line_out_level, cfg.data.tx_rig_out_level); // NOTE: need to see if this persists through input changes (see mic gain...)
audio_ctrl.micGain(cfg.data.tx_mic_in_gain); // superfluous, as I have to do this anytime I switch to mic for some reason
// configure line input
audio_ctrl.lineInLevel(cfg.data.rx_rig_in_level, cfg.data.tx_line_in_level);
// configure line output
tx_rig_out_cal.gain(cfg.data.tx_rig_out_cal);
audio_ctrl.lineOutLevel(cfg.data.rx_line_out_level, cfg.data.tx_rig_out_level);
// configure "receive" of USB audio input (debug only)
if (cfg.data.rx_usb_in_enable) {
rx_in_mix.gain(RX_USB_IN, cfg.data.rx_usb_in_vol * cfg.data.rx_usb_in_cal);
} else {
rx_in_mix.gain(RX_USB_IN, 0.0);
}
// configure USB audio output of transmit audio (useful for debug)
if (cfg.data.tx_usb_out_enable) {
tx_usb_out_cal.gain(cfg.data.tx_usb_out_cal);
} else {
tx_usb_out_cal.gain(0.0);
}
// setup the two-tone generator
sine1.frequency(700);
sine2.frequency(1900);
sine1.amplitude(0);
sine2.amplitude(0);
// no separate filter amp; just need to appropriately set the rx_out_mix values
rx_out_mix.gain(RX_BPF_ONLY, 1.0);
rx_out_mix.gain(RX_NOTCH_ON, 0.0);
// for now, just pass through the compressor
tx_comp.disable();
// Hardware should be all setup... now we're going to mute everything
// and let the modes take care of enabling/disabling what they should.
for (int i = 0; i < 4; i++) {
rx_in_mix.gain(i, 0.0);
tx_mix.gain(i, 0.0);
}
audio_equalizer();
USBDEBUG("audio initialization completed");
}
void dsp_audio::mute_rx() {
rx_in_mix.gain(RX_RIG_IN, 0.0);
USBDEBUG("RX audio muted");
}
void dsp_audio::unmute_rx() {
audio_ctrl.inputSelect(AUDIO_INPUT_LINEIN);
rx_in_mix.gain(RX_RIG_IN, cfg.data.rx_rig_in_vol * cfg.data.rx_rig_in_cal);
USBDEBUG("RX audio unmuted");
}
void dsp_audio::mute_all_tx() {
mute_mic_in();
mute_line_in();
mute_usb_in();
mute_twotone_in();
USBDEBUG("all TX audio muted");
}
void dsp_audio::mute_mic_in() {
tx_mix.gain(TX_LINE_IN, 0.0);
USBDEBUG("Mic In audio muted");
}
void dsp_audio::unmute_mic_in() {
audio_ctrl.inputSelect(AUDIO_INPUT_MIC);
audio_ctrl.micGain(cfg.data.tx_mic_in_gain);
tx_mix.gain(TX_LINE_IN, cfg.data.tx_mic_in_vol * cfg.data.tx_mic_in_cal);
USBDEBUG("Mic In audio unmuted");
}
void dsp_audio::mute_line_in() {
tx_mix.gain(TX_LINE_IN, 0.0);
USBDEBUG("Line In audio muted");
}
void dsp_audio::unmute_line_in() {
audio_ctrl.inputSelect(AUDIO_INPUT_LINEIN);
tx_mix.gain(TX_LINE_IN, cfg.data.tx_line_in_vol * cfg.data.tx_line_in_cal);
USBDEBUG("Line In audio unmuted");
}
void dsp_audio::mute_usb_in() {
tx_mix.gain(TX_USB_IN, 0.0);
USBDEBUG("USB In audio muted");
}
void dsp_audio::unmuteUSBIn() {
tx_mix.gain(TX_USB_IN, cfg.data.tx_usb_in_vol * cfg.data.tx_usb_in_cal);
USBDEBUG("USB In audio unmuted");
}
void dsp_audio::mute_twotone_in() {
tx_mix.gain(TX_TEST_IN, 0.0);
tx_mix.gain(TX_TEST_IN + 1, 0.0);
sine1.amplitude(0.0);
sine2.amplitude(0.0);
USBDEBUG("Two Tone audio muted");
}
void dsp_audio::unmute_twotone_in() {
sine1.amplitude(0.5);
sine2.amplitude(0.5);
tx_mix.gain(TX_TEST_IN, cfg.data.tx_sine1_vol);
tx_mix.gain(TX_TEST_IN + 1, cfg.data.tx_sine2_vol);
USBDEBUG("Two Tone audio unmuted");
}
void dsp_audio::mute_spkr_out() {
rx_spkr_out_cal.gain(0.0);
USBDEBUG("Speaker Out audio muted");
}
void dsp_audio::unmute_spkr_out() {
rx_spkr_out_cal.gain(cfg.data.rx_spkr_out_cal);
USBDEBUG("Speaker Out audio unmuted");
}
void dsp_audio::mute_line_out() {
rx_line_out_cal.gain(0.0);
USBDEBUG("Line Out audio muted");
}
void dsp_audio::unmute_line_out() {
rx_line_out_cal.gain(cfg.data.rx_line_out_cal);
USBDEBUG("Line Out audio unmuted");
}
void dsp_audio::mute_usb_out() {
rx_usb_out_cal.gain(0.0);
USBDEBUG("USB Out audio muted");
}
void dsp_audio::unmute_usb_out() {
rx_usb_out_cal.gain(cfg.data.rx_usb_out_cal);
USBDEBUG("USB Out audio unmuted");
}
//======================================================================
// bp_filter
//
// Band Pass Filter methods.
//======================================================================
bp_filter::bp_filter(): filter(filterRX), amp(filterAmp) {}
bp_filter::bp_filter(AudioFilterFIR& f, AudioAmplifier& a): filter(f), amp(a) {}
void bp_filter::init(const bpf_config& cfg) {
set_band(cfg.lo_freq, cfg.hi_freq);
set_gain(cfg.gain);
}
void bp_filter::set_band(double f1, double f2) {
freq_lo = f1;
freq_hi = f2;
}
void bp_filter::set_freq_lo(double f) { freq_lo = f; }
void bp_filter::set_freq_hi(double f) { freq_hi = f; }
void bp_filter::set_center_and_width(double c, double w) {
freq_lo = c - (0.5 * w);
freq_hi = c + (0.5 * w);
}
void bp_filter::set_center(double c) {
double w = freq_hi - freq_lo;
set_center_and_width(c, w);
}
void bp_filter::set_width(double w) {
double c = (freq_lo + freq_hi) * 0.5;
set_center_and_width(c, w);
}
void bp_filter::set_gain(double g) { recovery = g; }
void bp_filter::enable() {
audioFilter(coefficients, NUM_COEFFICIENTS, ID_BANDPASS, W_HAMMING, freq_lo, freq_hi);
filter.begin(coefficients, NUM_COEFFICIENTS);
amp.gain(recovery);
}
void bp_filter::disable() {
filter.begin(FIR_PASSTHRU, NUM_COEFFICIENTS);
amp.gain(1.0);
}
//======================================================================
speech_comp::speech_comp(comp_config* cfg) :
config_(cfg), comp_(compTX), amp_(compAmp), rms_(compRMS) {}
void speech_comp::enable()
{
config_->enabled = true;
comp_.begin(1, config_->threshold, config_->ratio); // Need to make configurable
amp_.gain(config_->gain);
}
void speech_comp::disable()
{
config_->enabled = false;
comp_.disable();
amp_.gain(1.0);
}
// Speech compressor code based on post by 'hyperdyne': https://forum.pjrc.com/threads/36245-Changing-Pitch-of-Voice
void speech_comp::update()
{
float rms_cur;
if (config_->enabled && rms_.available()) {
rms_cur = rms_.read();
env_ = rms_cur + (alpha_ * (env_ - rms_cur));
comp_.update_pwr(env_);
}
}
//======================================================================
void dsp_audio::audio_equalizer()
{
static int eqFilter1[5];
audioCtrl.audioPreProcessorEnable();
audioCtrl.eqSelect(PARAMETRIC_EQUALIZER);
// calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*);
calcBiquad(FILTER_PARAEQ, 2700, 6, 0.707, 524288, 44100, eqFilter1);
// calcBiquad(FILTER_HIPASS, 100, 0, 0.707, 524288, 44100, hpFilter);
audioCtrl.eqFilter(0, eqFilter1);
// audioCtrl.eqFilter(1, hpFilter);
// audioCtrl.eqFilter(2, lpFilter);
// audioCtrl.eqFilter(3, hpFilter);
// audioCtrl.eqFilter(4, lpFilter);
// audioCtrl.eqFilter(5, hpFilter);
}
//======================================================================
// EOF
//======================================================================

120
digibox/dsp_audio.h Normal file
View File

@ -0,0 +1,120 @@
//======================================================================
// dsp_audio.h
//======================================================================
#ifndef __dsp_audio_h__
#define __dsp_audio_h__
#include <Audio.h>
#include <dynamicFilters.h>
#include <effect_compressor_fb.h>
#include "config.h"
namespace dsp_audio
{
void init(dsp_audio_cfg& c);
void update(int msec);
void mute_rx();
void unmute_rx();
void mute_all_tx();
void mute_mic_in();
void unmute_mic_in();
void mute_line_in();
void unmute_line_in();
void mute_usb_in();
void unmute_usb_in();
void mute_twotone_in();
void unmute_twotone_in();
void mute_spkr_out();
void unmute_spkr_out();
void mute_line_out();
void unmute_line_out();
void mute_usb_out();
void unmute_usb_out();
//======================================================================
class bp_filter {
public:
bp_filter();
bp_filter(AudioFilterFIR& f, AudioAmplifier& a);
void init(const bpf_config& cfg);
void set_band(double f1, double f2);
void set_freq_lo(double f);
void set_freq_hi(double f);
void set_center_and_width(double c, double w);
void set_center(double c);
void set_width(double w);
void set_gain(double g);
void enable();
void disable();
private:
double freq_lo;
double freq_hi;
short int window;
short int coeff;
float recovery; // recovery amplifier value
AudioFilterFIR& filter; // = &filterRX;
AudioAmplifier& amp;
short coefficients[NUM_COEFFICIENTS];
bool setup_complete;
};
//======================================================================
class notch_filter
{
public:
notch_filter(notch_config& cfg);
void enable();
void disable();
inline bool is_enabled() const { return config_.enabled; }
private:
notch_config& config_;
double freq_;
double q_;
};
//======================================================================
class speech_comp
{
public:
speech_comp(comp_config& cfg);
void update();
void enable();
void disable();
inline bool is_enabled() const { return config_.enabled; }
private:
comp_config& config_;
AudioEffectCompressor& comp_;
AudioAmplifier& amp_;
AudioAnalyzeRMS& rms_;
float env_ = 1.0;
float alpha_ = 0.8;
};
};
#endif
//======================================================================
// EOF
//======================================================================

75
digibox/ubitx-dsp.h Normal file
View File

@ -0,0 +1,75 @@
//======================================================================
// ubitx_iop.h
//======================================================================
#ifndef __ubitx_iop_h__
#define __ubitx_iop_h__
#include "config.h"
#include "audio.h"
#include "cat.h"
#include "eeprom.h"
#include "keyer.h"
#define PTT_KEY_OUT_PIN 2
#define ENCODER_A_PIN 5
#define ENCODER_B_PIN 4
#define ENCODER_SW_PIN 3
// comment this out to disable debugging code
#define DEBUG
#if defined(DEBUG)
#define USBDEBUG(x) USBSERIAL.print("IOP: "); USBSERIAL.println(x);
#else
#define USBDEBUG(x)
#endif
//enum RigMode {
// MODE_SSB = 0,
// MODE_DIGI = 1,
// MODE_CW = 2,
//};
enum TxState {
TX_OFF = 0,
TX_MIC,
TX_LINE,
TX_CAT,
TX_KEYER,
};
//extern RigMode rigMode;
extern bool keyerKeyDown;
//======================================================================
// Keying functions.
//
// These are simple functions to assert the key line from the IOP to the
// Raduino.
//======================================================================
inline void initKeyLine()
{
pinMode(PTT_KEY_OUT_PIN, OUTPUT);
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
}
inline void setKeyDown()
{
digitalWrite(PTT_KEY_OUT_PIN, LOW);
}
inline void setKeyUp()
{
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
}
//======================================================================
#endif
//======================================================================
// EOF
//======================================================================

235
digibox/ubitx-dsp.ino Normal file
View File

@ -0,0 +1,235 @@
//======================================================================
// 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
//======================================================================