Insanely, this also compiles.

Numerous changes updating modes, rig, config, everything... don't think
this ones gonna work first time through...
This commit is contained in:
Rob French 2020-06-14 00:11:18 -05:00
parent 2da162f7c2
commit 6581a5f2a4
12 changed files with 426 additions and 1287 deletions

View File

@ -97,41 +97,39 @@ enum MessageID {
* (e.g. USB, LSB, etc.)
*/
enum rig_mode {
lsb = 0,
usb,
enum struct rig_mode {
ssb = 0,
cw,
cwr,
dig,
digi,
// add new items here
num_rig_modes
count
};
/* Keyer modes.
*/
enum keyer_mode {
enum struct keyer_mode {
straight = 0,
iambic_a,
iambic_b,
//ultimatic,
//bug,
// add any new items here
num_keyer_modes
count
};
enum rx_filter {
enum struct rx_filter {
wide = 0,
medium,
narrow,
num_rx_filters
count
};
enum digi_mode {
enum struct digi_submode {
rtty = 0,
psk31,
user_defined,
num_digi_modes
count
};
//const unsigned char RIG_MODE_LETTER[num_rig_modes] = {'s', 'S', 'c', 'C', 'd', 'D', 't', 'T'};
@ -154,67 +152,70 @@ struct IOPMessage {
// Interface to a configuration object.
//======================================================================
struct filter_config {
float lo;
float hi;
struct bpf_config {
float lo_freq;
float hi_freq;
float gain;
};
struct mode_config {
mode_config(bool usb, rx_filter f, const filter_config *fc) : is_usb(usb), filter(f) {
for (int i = 0; i < num_rx_filters; i++) {
filtercfg[i] = fc[i];
mode_config(bool usb, rx_filter f, const bpf_config *fc) : is_usb(usb), filter(f) {
for (int i = 0; i < static_cast<int>(rx_filter::count); i++) {
filter_cfg[i] = fc[i];
}
}
bool is_usb;
rx_filter filter;
filter_config filtercfg[num_rx_filters];
bool is_usb;
rx_filter filter;
bpf_config filter_cfg[static_cast<size_t>(rx_filter::count)];
};
//======================================================================
// SSB CONFIGURATION
//======================================================================
const filter_config ssb_filter_config[num_rx_filters] =
{filter_config{ 300.0, 3100.0, 1.0},
filter_config{ 500.0, 2900.0, 1.0},
filter_config{ 700.0, 2500.0, 1.0}};
const bpf_config ssb_filter_config[] =
{bpf_config{ 300.0, 3100.0, 1.0},
bpf_config{ 500.0, 2900.0, 1.0},
bpf_config{ 700.0, 2500.0, 1.0}};
struct comp_config {
bool enabled = false;
float threshold = 0.1;
float ratio = 20.0;
float gain = 2.0;
};
struct ssb_config : public mode_config {
ssb_config() : mode_config(true, wide, ssb_filter_config) {}
// speech compressor parameters
bool comp_enable = false;
float comp_threshold = 0.1;
float comp_ratio = 20.0;
float comp_gain = 2.0;
ssb_config() : mode_config(true, rx_filter::wide, ssb_filter_config) {}
comp_config comp;
};
//======================================================================
// DIG CONFIGURATION
// DIGI CONFIGURATION
//======================================================================
const filter_config dig_filter_config[num_rx_filters] =
{filter_config{ 300.0, 3100.0, 1.0},
filter_config{ 500.0, 2900.0, 1.0},
filter_config{1250.0, 1750.0, 1.0}};
const bpf_config digi_filter_config[] =
{bpf_config{ 300.0, 3100.0, 1.0},
bpf_config{ 500.0, 2900.0, 1.0},
bpf_config{1250.0, 1750.0, 1.0}};
struct dig_config : public mode_config {
dig_config() : mode_config(true, wide, dig_filter_config) {}
digi_mode submode = user_defined;
struct digi_config : public mode_config {
digi_config() : mode_config(true, rx_filter::wide, digi_filter_config) {}
digi_submode submode = digi_submode::user_defined;
};
//======================================================================
// CW CONFIGURATION
//======================================================================
const filter_config cw_filter_config[num_rx_filters] =
{filter_config{ 300.0, 1300.0, 1.0},
filter_config{ 450.0, 950.0, 1.0},
filter_config{ 575.0, 825.0, 1.0}};
const bpf_config cw_filter_config[] =
{bpf_config{ 300.0, 1300.0, 1.0},
bpf_config{ 450.0, 950.0, 1.0},
bpf_config{ 575.0, 825.0, 1.0}};
struct cw_config : public mode_config {
cw_config() : mode_config(true, wide, cw_filter_config) {}
keyer_mode mode = iambic_a;
cw_config() : mode_config(true, rx_filter::wide, cw_filter_config) {}
keyer_mode mode = keyer_mode::iambic_a;
// flags
bool reversed = false;
// parameters

View File

@ -7,147 +7,160 @@
#include "audio.h"
// Exceptions not active (for Arduino, I assume?).
//enum IModeExceptions {
// MODE_ALREADY_ACTIVE = -1,
// MODE_STILL_TRANSMITTING = -2,
// MODE_ALREADY_TRANSMITTING = -3,
// MODE_NOT_TRANSMITTING = -4,
//};
//======================================================================
// IMode
// basic_mode
//
// Interface to a rig mode (SSB, CW, etc.).
// A basic rig mode. It can perform actions on_entry() and on_exit(),
// as well as on_tx() and on_rx(). These actions are defined in an
// appropriate subclass. In addition, the basic mode support an audio
// audio band pass filter with wide, medium, and narrow modes.
//======================================================================
class IMode {
class basic_mode {
public:
IMode(mode_config& c, RigAudio& a, IFilter& f):
_config(c), _audio(a), _filter(f), _active(false), _transmitting(false)
basic_mode(mode_config& c, RigAudio& a, bp_filter& f) :
config_(c), audio_(a), filter_(f), active_(false), transmitting_(false)
{
}
virtual ~IMode() {}
virtual ~basic_mode() {}
inline mode_config& config() { return _config; }
inline mode_config& config() { return config_; }
inline RigAudio& audio() { return _audio; }
inline RigAudio& audio() { return audio_; }
inline IFilter& filter() { return _filter; }
inline bp_filter& filter() { return filter_; }
// Called upon mode entry. Should assume that the rig's state is
// "clean", i.e. that it still needs to enable anything it needs for
// use in the mode.
virtual void onEntry() = 0;
virtual void on_entry() = 0;
// Called upon mode exit. Should clean everything up that it used,
// and not make assumptions about which mode is being entered next.
virtual void onExit() = 0;
virtual void on_exit() = 0;
// Called when transmitting.
virtual void onTx() = 0;
virtual void on_tx() = 0;
// Called when receiving.
virtual void onRx() = 0;
virtual void on_rx() = 0;
inline void enter() {
if (_active) {
if (active_) {
// Do nothing. Exceptions not active (for Arduino, I assume?).
//throw MODE_ALREADY_ACTIVE;
USBDEBUG("ERROR - tried to enter mode, but it's already active");
} else {
_active = true;
onEntry();
active_ = true;
on_entry();
}
}
inline void exit() {
if (_transmitting) {
if (transmitting_) {
// Do nothing. Exceptions not active (for Arduino, I assume?).
//throw MODE_STILL_TRANSMITTING;
USBDEBUG("ERROR - tried to exit mode, but it's transmitting");
} else {
_active = false;
onExit();
active_ = false;
on_exit();
}
}
inline bool isActive() { return _active; }
inline bool isInactive() { return !_active; }
inline bool is_active() { return active_; }
inline bool is_inactive() { return !active_; }
inline void tx() {
if (_transmitting) {
if (transmitting_) {
// Do nothing. Exceptions not active (for Arduino, I assume?).
//throw MODE_ALREADY_TRANSMITTING;
USBDEBUG("ERROR - tried to start transmitting, but mode already is transmitting");
} else {
_transmitting = true;
onTx();
transmitting_ = true;
on_tx();
}
}
inline void rx() {
if (!_transmitting) {
if (!transmitting_) {
// Do nothing. Exceptions not active (for Arduino, I assume?).
//throw MODE_NOT_TRANSMITTING;
USBDEBUG("ERROR - tried to start receiving, but mode already is receiving");
} else {
_transmitting = false;
onRx();
transmitting_ = false;
on_rx();
}
}
inline bool isTx() const { return _transmitting; }
inline bool isRx() const { return !_transmitting; }
inline bool is_tx() const { return transmitting_; }
inline bool is_rx() const { return !transmitting_; }
virtual void setWideRxFilter() = 0;
inline void set_rx_filter(rx_filter f) {
filter_.disable();
config_.filter = f;
filter_.init(config_.filter_cfg[static_cast<int>(config_.filter)]);
filter_.enable();
#if defined(DEBUG)
switch(config_.filter) {
case rx_filter::wide:
USBDEBUG("selected wide filter");
break;
virtual void setMediumRxFilter() = 0;
case rx_filter::medium:
USBDEBUG("selected medium filter");
break;
virtual void setNarrowRxFilter() = 0;
case rx_filter::narrow:
USBDEBUG("selected narrow filter");
break;
}
#endif
}
private:
mode_config& _config;
RigAudio& _audio;
IFilter& _filter;
bool _active;
bool _transmitting;
mode_config& config_;
RigAudio& audio_;
bp_filter& filter_;
bool active_;
bool transmitting_;
};
//======================================================================
// SSBMode
// ssb_mode
//======================================================================
class SSBMode : public IMode
class ssb_mode : public basic_mode
{
public:
SSBMode(mode_config& c, RigAudio& a, IFilter& f, bool default_mic=true):
IMode(c, a, f), _use_mic(default_mic)
{
}
ssb_mode(ssb_config& c, RigAudio& a, bp_filter& f, speech_comp& s, bool default_mic=true) :
basic_mode(c, a, f), use_mic_(default_mic), comp_(s) {}
virtual void onEntry()
virtual void on_entry()
{
setWideRxFilter();
set_rx_filter(config().filter);
if (comp_.is_enabled()) {
enable_comp();
}
audio().unmuteRx();
audio().muteAllTx();
USBDEBUG("SSB mode entered");
}
virtual void onExit() {
virtual void on_exit() {
audio().muteAllTx();
audio().muteRx();
disable_comp();
USBDEBUG("SSB mode exited");
}
virtual void onTx()
virtual void on_tx()
{
audio().muteRx();
if (_use_mic) {
if (use_mic_) {
audio().unmuteMicIn();
} else {
audio().unmuteLineIn();
@ -155,9 +168,9 @@ class SSBMode : public IMode
USBDEBUG("SSB mode transmitting");
}
virtual void onRx()
virtual void on_rx()
{
if (_use_mic) {
if (use_mic_) {
audio().muteMicIn();
} else {
audio().muteLineIn();
@ -166,137 +179,100 @@ class SSBMode : public IMode
USBDEBUG("SSB mode receiving");
}
void setMicIn()
void set_mic_in()
{
if (isRx()) {
if (is_rx()) {
// can't switch inputs while already transmitting
_use_mic = true;
use_mic_ = true;
}
USBDEBUG("SSB mode - Mic In set");
}
void setLineIn()
void set_line_in()
{
if (isRx()) {
if (is_rx()) {
// can't switch inputs while already transmitting
_use_mic = false;
use_mic_ = false;
}
USBDEBUG("SSB mode - Line In set");
}
virtual void setWideRxFilter() {
((BPFilter&)filter()).setBand(300.0, 3100.0);
filter().enable();
USBDEBUG("set wide RX SSB filter");
}
virtual void setMediumRxFilter() {
((BPFilter&)filter()).setBand(500.0, 2900.0);
filter().enable();
USBDEBUG("set medium RX SSB filter");
}
virtual void setNarrowRxFilter() {
((BPFilter&)filter()).setBand(700.0, 2500.0);
filter().enable();
USBDEBUG("set narrow RX SSB filter");
}
inline void enable_comp() { comp_.enable(); }
inline void disable_comp() { comp_.disable(); }
private:
bool _use_mic;
bool use_mic_;
speech_comp& comp_;
};
//======================================================================
// DGTMode
// digi_mode
//======================================================================
class DGTMode : public IMode
class digi_mode : public basic_mode
{
public:
DGTMode(mode_config& c, RigAudio& a, IFilter& f):
IMode(c, a, f)
{
}
digi_mode(digi_config& c, RigAudio& a, bp_filter& f) :
basic_mode(c, a, f) {}
virtual void onEntry()
virtual void on_entry()
{
setWideRxFilter();
set_rx_filter(config().filter);
audio().unmuteRx();
audio().muteAllTx();
USBDEBUG("DGT mode entered");
USBDEBUG("Digi mode entered");
}
virtual void onExit() {
virtual void on_exit() {
audio().muteAllTx();
audio().muteRx();
USBDEBUG("DGT mode exited");
USBDEBUG("Digi mode exited");
}
virtual void onTx()
virtual void on_tx()
{
audio().muteRx();
audio().unmuteUSBIn();
USBDEBUG("DGT mode transmitting");
USBDEBUG("Digi mode transmitting");
}
virtual void onRx()
virtual void on_rx()
{
audio().muteUSBIn();
audio().unmuteRx();
USBDEBUG("DGT mode receiving");
USBDEBUG("Digi mode receiving");
}
virtual void setWideRxFilter(){
((BPFilter&)filter()).setBand(300.0, 3100.0);
filter().enable();
USBDEBUG("set wide RX DGT filter");
}
virtual void setMediumRxFilter(){
((BPFilter&)filter()).setBand(500.0, 2900.0);
filter().enable();
USBDEBUG("set medium RX DGT filter");
}
virtual void setNarrowRxFilter(){
((BPFilter&)filter()).setCenterAndWidth(1500.0, 500.0);
filter().enable();
USBDEBUG("set narrow RX DGT filter");
}
};
//======================================================================
// CWMode
// cw_mode
//======================================================================
class CWMode : public IMode
class cw_mode : public basic_mode
{
public:
CWMode(mode_config& c, RigAudio& a, IFilter& f):
IMode(c, a, f)
{
}
cw_mode(cw_config& c, RigAudio& a, bp_filter& f):
basic_mode(c, a, f) {}
virtual void onEntry()
virtual void on_entry()
{
setWideRxFilter();
set_rx_filter(config().filter);
audio().unmuteRx();
audio().muteAllTx();
USBDEBUG("CW mode entered");
}
virtual void onExit() {
virtual void on_exit() {
audio().muteAllTx();
audio().muteRx();
USBDEBUG("CW mode exited");
}
virtual void onTx()
virtual void on_tx()
{
// Currently not muting Rx, since the uBITX produces it's own
// sidetone... but I'm probably going to replace that with a S/W-
@ -304,108 +280,10 @@ class CWMode : public IMode
USBDEBUG("CW mode transmitting");
}
virtual void onRx()
virtual void on_rx()
{
USBDEBUG("CW mode receiving");
}
virtual void setWideRxFilter(){
float st = float(((cw_config&)config()).sidetone);
float width = 1000.0;
float low = st - (width * 0.5);
if (low < 300.0) {
low = 300.0;
}
((BPFilter&)filter()).setBand(low, low + width);
filter().enable();
USBDEBUG("set wide RX CW filter");
}
virtual void setMediumRxFilter(){
float st = float(((cw_config&)config()).sidetone);
float width = 500.0;
float low = st - (width * 0.5);
if (low < 300.0) {
low = 300.0;
}
((BPFilter&)filter()).setBand(low, low + width);
filter().enable();
USBDEBUG("set medium RX CW filter");
}
virtual void setNarrowRxFilter(){
float st = float(((cw_config&)config()).sidetone);
float width = 250.0;
float low = st - (width * 0.5);
if (low < 300.0) {
low = 300.0;
}
((BPFilter&)filter()).setBand(low, low + width);
filter().enable();
USBDEBUG("set narrow RX CW filter");
}
};
//======================================================================
// TTMode
//======================================================================
class TTMode : public IMode
{
public:
TTMode(mode_config& c, RigAudio& a, IFilter& f):
IMode(c, a, f)
{
}
virtual void onEntry()
{
setWideRxFilter();
audio().unmuteRx();
audio().muteAllTx();
USBDEBUG("Test (Two-Tone) mode entered");
}
virtual void onExit() {
audio().muteAllTx();
audio().muteRx();
USBDEBUG("Test (Two-Tone) mode exited");
}
virtual void onTx()
{
audio().muteRx();
audio().unmuteTTIn();
USBDEBUG("Test (Two-Tone) mode transmitting");
}
virtual void onRx()
{
audio().muteTTIn();
audio().unmuteRx();
USBDEBUG("Test (Two-Tone) mode receiving");
}
virtual void setWideRxFilter(){
((BPFilter&)filter()).setBand(300.0, 3100.0);
filter().enable();
USBDEBUG("set wide RX TT filter");
}
virtual void setMediumRxFilter(){
((BPFilter&)filter()).setBand(500.0, 2900.0);
filter().enable();
USBDEBUG("set medium RX TT filter");
}
virtual void setNarrowRxFilter(){
((BPFilter&)filter()).setBand(700.0, 2500.0);
filter().enable();
USBDEBUG("set narrow RX TT filter");
}
};
#endif

View File

@ -29,12 +29,12 @@ class ITxSwitch
virtual ~ITxSwitch() {}
// Called before beginning transmit; if false, transmit aborts before starting.
virtual bool onPress(IMode* m) = 0;
virtual bool onPress(basic_mode* m) = 0;
// Called before stopping tranmit; if false, transmit continues.
virtual bool onRelease(IMode* m) = 0;
virtual bool onRelease(basic_mode* m) = 0;
void press(IMode* m, bool output_enable=true) {
void press(basic_mode* m, bool output_enable=true) {
if (onPress(m)) {
USBDEBUG("PTT pressed");
m->tx();
@ -44,7 +44,7 @@ class ITxSwitch
}
}
void release(IMode* m, bool output_enable=true) {
void release(basic_mode* m, bool output_enable=true) {
if (onRelease(m)) {
USBDEBUG("PTT released");
if (output_enable) {
@ -68,10 +68,10 @@ class CATSwitch : public ITxSwitch
public:
CATSwitch(): _transmitting(false) {}
virtual bool onPress(IMode* m) {
virtual bool onPress(basic_mode* m) {
// If another transmission is already occuring, abort... CAT can't
// interrupt transmissions already ongoing.
if (m->isRx()) {
if (m->is_rx()) {
USBDEBUG("CAT PTT pressed");
_transmitting = true;
return true;
@ -80,7 +80,7 @@ class CATSwitch : public ITxSwitch
}
}
virtual bool onRelease(IMode* m) {
virtual bool onRelease(basic_mode* m) {
// If CAT transmission is not occurring, abort... CAT can't stop
// transmissions initiated by other sources. We don't check if
// the mode is already transmitting, because it could be
@ -98,90 +98,6 @@ class CATSwitch : public ITxSwitch
bool _transmitting; // CAT-specific transmission
};
/*
//----------------------------------------------------------------------
// MicSwitch
//
// Implementation of the ITxSwitch interface for the Mic (front panel)
// switch. Features:
// - In SSB, it will automatically select the Mic (front panel) input.
// - If already transmitting, press will have no effect.
// - If already transmitting (any mode, source), release will stop
// the transmission... a failsafe.
//----------------------------------------------------------------------
class MicSwitch : public ITxSwitch
{
public:
MicSwitch(): _ssb_mode(false) {}
inline void setSSBMode(bool flag) { _ssb_mode = flag; }
virtual bool onPress(IMode* m) {
if (m->isRx()) {
if (_ssb_mode) {
((SSBMode*)m)->setMicIn();
}
return true;
} else {
return false;
}
}
virtual bool onRelease(IMode* m) {
if (m->isTx()) {
return true;
} else {
return false;
}
}
private:
bool _ssb_mode;
};
//----------------------------------------------------------------------
// LineSwitch
//
// Implementation of the ITxSwitch interface for the Line (rear panel)
// switch. Features:
// - In SSB, it will automatically select the Line (rear panel) input.
// - If already transmitting, press will have no effect.
// - If already transmitting (any mode, source), release will stop
// the transmission... a failsafe.
//----------------------------------------------------------------------
class LineSwitch : public ITxSwitch
{
public:
LineSwitch(): _ssb_mode(false) {}
inline void setSSBMode(bool flag) { _ssb_mode = flag; }
virtual bool onPress(IMode* m) {
if (m->isRx()) {
if (_ssb_mode) {
((SSBMode*)m)->setLineIn();
}
return true;
} else {
return false;
}
}
virtual bool onRelease(IMode* m) {
if (m->isTx()) {
return true;
} else {
return false;
}
}
private:
bool _ssb_mode;
};
*/
//----------------------------------------------------------------------
// GPIOSwitch
//
@ -201,15 +117,15 @@ class GPIOSwitch : public ITxSwitch
inline void setSSBMode(bool flag) { _ssb_mode = flag; }
virtual bool onPress(IMode* m) {
if (m->isRx()) {
virtual bool onPress(basic_mode* m) {
if (m->is_rx()) {
if (_ssb_mode) {
if (_is_mic) {
USBDEBUG("Mic PTT pressed");
((SSBMode*)m)->setMicIn();
((ssb_mode*)m)->set_mic_in();
} else {
USBDEBUG("Line PTT pressed");
((SSBMode*)m)->setLineIn();
((ssb_mode*)m)->set_line_in();
}
}
return true;
@ -218,15 +134,15 @@ class GPIOSwitch : public ITxSwitch
}
}
virtual bool onRelease(IMode* m) {
if (m->isTx()) {
virtual bool onRelease(basic_mode* m) {
if (m->is_tx()) {
return true;
} else {
return false;
}
}
void update(IMode* m, bool output_enable=true) {
void update(basic_mode* m, bool output_enable=true) {
_bounce.update();
if (_bounce.fell()) {

View File

@ -8,6 +8,8 @@
#define __iop_audio_h__
#include <Audio.h>
#include <dynamicFilters.h>
#include <effect_compressor_fb.h>
#include "config.h"
class RigAudio
@ -49,38 +51,57 @@ class RigAudio
//======================================================================
class IFilter {
public:
virtual ~IFilter() {}
virtual void enable() = 0;
virtual void disable() = 0;
};
class BPFilter : public IFilter {
class bp_filter {
public:
BPFilter(double f1, double f2, bool use_center, short int window=-1, short int coeff=-1);
void init(AudioFilterFIR* filter=NULL, short* coefficients=NULL);
void setFreqLo(double f);
void setFreqHi(double f);
void setBand(double f1, double f2);
void setCenter(double c);
void setWidth(double w);
void setCenterAndWidth(double c, double w);
virtual void enable();
virtual void disable();
//bp_filter(double f1, double f2, bool use_center, short int window=-1, short int coeff=-1);
bp_filter();
bp_filter(AudioFilterFIR& f, AudioAmplifier& a);
void init(const bpf_config& cfg);
//void init(AudioFilterFIR* filter=NULL, short* coefficients=NULL);
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
double freq_lo;
double freq_hi;
short int window;
short int coeff;
float recovery; // recovery amplifier value
AudioFilterFIR* _filter; // = &filterRX;
short* _coefficients;
AudioFilterFIR& filter; // = &filterRX;
AudioAmplifier& amp;
short coefficients[NUM_COEFFICIENTS];
bool setup_complete;
};
//======================================================================
class speech_comp
{
public:
speech_comp(comp_config* cfg);
// speech_comp(AudioEffectCompressor&, AudioAmplifier&, AudioAnalyzeRMS&);
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;
};
//======================================================================

View File

@ -8,10 +8,7 @@
#include <dynamicFilters.h>
#include <effect_compressor_fb.h>
#include "audio.h"
#include "tx_audio_proc.h"
//short firActive[NUM_COEFFICIENTS];
@ -266,471 +263,91 @@ TxInput audioTxInput;
TxOutput audioTxOutput;
*/
//======================================================================
// bp_filter
//
// Band Pass Filter methods.
//======================================================================
short _internal_coefficients[NUM_COEFFICIENTS];
bp_filter::bp_filter(): filter(filterRX), amp(filterAmp) {}
BPFilter::BPFilter(double f1, double f2, bool use_center=false, short int window, short int coeff):
_window(window), _coeff(coeff)
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()
{
if (window == -1) {
_window = W_HAMMING;
}
if (coeff == -1) {
_coeff = NUM_COEFFICIENTS;
}
if (use_center) { // treat f1 as center frequency, f2 as filter width
_freq_lo = f1 - (0.5 * f2);
_freq_hi = f1 + (0.5 * f2);
} else {
_freq_lo = f1;
_freq_hi = f2;
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 BPFilter::init(AudioFilterFIR* filter, short* coefficients) {
if (filter == NULL) {
_filter = &filterRX;
} else {
_filter = filter;
}
if (coefficients == NULL) {
_coefficients = _internal_coefficients;
} else {
_coefficients = coefficients;
}
//audioFilter(coefficients, NUM_COEFFICIENTS, ID_BANDPASS, _window, _freq_lo, _freq_hi);
//filter->begin(coefficients, NUM_COEFFICIENTS);
}
void BPFilter::setFreqLo(double f) { _freq_lo = f; }
void BPFilter::setFreqHi(double f) { _freq_hi = f; }
void BPFilter::setBand(double f1, double f2) {
_freq_lo = f1;
_freq_hi = f2;
}
void BPFilter::setCenter(double c) {
double w = _freq_hi - _freq_lo;
setCenterAndWidth(c, w);
}
void BPFilter::setWidth(double w) {
double c = (_freq_lo + _freq_hi) * 0.5;
setCenterAndWidth(c, w);
}
void BPFilter::setCenterAndWidth(double c, double w) {
_freq_lo = c - (0.5 * w);
_freq_hi = c + (0.5 * w);
}
void BPFilter::enable() {
audioFilter(_coefficients, NUM_COEFFICIENTS, ID_BANDPASS, _window, _freq_lo, _freq_hi);
_filter->begin(_coefficients, NUM_COEFFICIENTS);
}
void BPFilter::disable() {
_filter->begin(FIR_PASSTHRU, NUM_COEFFICIENTS);
}
//======================================================================
SpeechCompressor speechCompressor(compTX, compAmp, compRMS);
//======================================================================
/*
// array based on mode right now
BPFilter *rxFilter[NUM_RIG_MODES][NUM_RX_FILTERS];
//======================================================================
void audioSetupFilters()
{
rxFilter[RIG_MODE_SSB][FILTER_WIDE] = new BPFilter( 300.0, 3100.0);
rxFilter[RIG_MODE_SSB][FILTER_NORMAL] = new BPFilter( 500.0, 2900.0);
rxFilter[RIG_MODE_SSB][FILTER_NARROW] = new BPFilter( 700.0, 2500.0);
// Need to make the NARROW filter center frequency configurable.
rxFilter[RIG_MODE_DIGI][FILTER_WIDE] = new BPFilter( 300.0, 3100.0);
rxFilter[RIG_MODE_DIGI][FILTER_NORMAL] = new BPFilter( 500.0, 2900.0);
rxFilter[RIG_MODE_DIGI][FILTER_NARROW] = new BPFilter(1500.0, 500.0, true);
// Need to use the sidetone frequency for the NORMAL and NARROW filters.
rxFilter[RIG_MODE_CW][FILTER_WIDE] = new BPFilter( 300.0, 1300.0);
rxFilter[RIG_MODE_CW][FILTER_NORMAL] = new BPFilter( 700.0, 500.0, true);
rxFilter[RIG_MODE_CW][FILTER_NARROW] = new BPFilter( 700.0, 250.0, true);
}
//======================================================================
SpeechCompressor speechCompressor(compTX, compAmp, compRMS);
//======================================================================
// audioInit()
// Setup the audio subsystem.
void audioInit()
{
audioCtrl.enable();
audioCtrl.muteHeadphone(); // not using the headphone output
audioCtrl.volume(0.0); // not using the headphone output
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN); // required for RX audio
audioCtrl.unmuteLineout(); // required for RX audio
audioCtrl.lineInLevel(rigConfig.rxRigInLevel, rigConfig.txLineInLevel); // NOTE: need to see if this persists through input changes (see mic gain...)
audioCtrl.lineOutLevel(rigConfig.rxLineOutLevel, rigConfig.txRigOutLevel); // NOTE: need to see if this persists through input changes (see mic gain...)
audioCtrl.micGain(rigConfig.txMicInGain); // superfluous, as I have to do this anytime I switch to mic for some reason
//audioCtrl.dacVolumeRamp(); // if this seems too slow, might try dacVolumeRampLinear().
//audioCtrl.dacVolume(1.0, 0.0); // we're going to mute TX audio via the DAC unless we're transmitting
updateRxRigIn();
updateRxSpkrOut();
updateRxLineOut();
updateRxUSBOut();
// Note - these really just need to be init functions; keep things muted while setting them up.
updateTxMicIn();
updateTxLineIn();
updateTxUSBIn();
updateTxTwoToneIn();
updateTxRigOut();
audioSelectRxInput(RX_RIG_IN);
audioSelectTxInput(TX_MIC_IN); // superfluous I think
//audioCtrl.adcHighPassFilterDisable();
//audioCtrl.audioPreProcessorEnable();
// setup the two-tone generator
sine1.frequency(700);
sine2.frequency(1900);
sine1.amplitude(0);
sine2.amplitude(0);
//audioFilter(firActive, NUM_COEFFICIENTS, ID_BANDPASS, W_HAMMING, 300.0, 3100.0); // 2.8 kHz filter
//filterRX.begin(firActive, NUM_COEFFICIENTS);
filterAmp.gain(1.0);
// for now, just pass through the compressor
//compTX.disable();
//compAmp.gain(1.0);
speechCompressor.enable();
}
//======================================================================
//======================================================================
void audioCalibrate(AudioConfig* c, char cmd, char subcmd, char parm, float value, bool set_value=true)
{
switch(cmd) {
case 'r':
case 'R':
// RX audio parameters
switch(subcmd) {
case 'r':
case 'R':
// Rig input
switch(parm) {
case 'l':
case 'L':
// level
if (set_value) {
c->rxRigInLevel = int(value);
updateRxRigIn();
}
USBSERIAL.print("rxRigInLevel: ");
USBSERIAL.println(c->rxRigInLevel);
break;
case 'v':
case 'V':
// volume
if (set_value) {
c->rxRigInVol = value;
updateRxRigIn();
}
USBSERIAL.print("rxRigInVol: ");
USBSERIAL.println(c->rxRigInVol);
break;
case 'c':
case 'C':
// calibration
if (set_value) {
c->rxRigInCal = value;
updateRxRigIn();
}
USBSERIAL.print("rxRigInCal: ");
USBSERIAL.println(c->rxRigInCal);
break;
}
break;
case 's':
case 'S':
// Speaker output
switch(parm) {
case 'c':
case 'C':
// calibration
if (set_value) {
c->rxSpkrOutCal = value;
updateRxSpkrOut();
}
USBSERIAL.print("rxSpkrOutCal: ");
USBSERIAL.println(c->rxSpkrOutCal);
break;
}
break;
case 'l':
case 'L':
// Line output
switch(parm) {
case 'l':
case 'L':
// level
if (set_value) {
c->rxLineOutLevel = int(value);
updateRxLineOut();
}
USBSERIAL.print("rxLineOutLevel: ");
USBSERIAL.println(c->rxLineOutLevel);
break;
case 'c':
case 'C':
// calibration
if (set_value) {
c->rxLineOutCal = value;
updateRxLineOut();
}
USBSERIAL.print("rxLineOutCal: ");
USBSERIAL.println(c->rxLineOutCal);
break;
}
break;
case 'u':
case 'U':
// USB output
switch(parm) {
case 'c':
case 'C':
// calibration
if (set_value) {
c->rxUSBOutCal = value;
updateRxUSBOut();
}
USBSERIAL.print("rxUSBOutCal: ");
USBSERIAL.println(c->rxUSBOutCal);
break;
}
break;
}
break;
case 't':
case 'T':
//TX audio parameters
switch(subcmd) {
case 'm':
case 'M':
// Mic input
switch(parm) {
case 'g':
case 'G':
// mic gain
if (set_value) {
c->txMicInGain = int(value);
updateTxMicIn();
}
USBSERIAL.print("txMicInGain: ");
USBSERIAL.println(c->txMicInGain);
break;
case 'v':
case 'V':
// volume
if (set_value) {
c->txMicInVol = value;
updateTxMicIn();
}
USBSERIAL.print("txMicInVol: ");
USBSERIAL.println(c->txMicInVol);
break;
case 'c':
case 'C':
// calibration
if (set_value) {
c->txMicInCal = value;
updateTxMicIn();
}
USBSERIAL.print("txMicInCal: ");
USBSERIAL.println(c->txMicInCal);
break;
}
break;
case 'l':
case 'L':
// Line input
switch(parm) {
case 'l':
case 'L':
// level
if (set_value) {
c->txLineInLevel = int(value);
updateTxLineIn();
}
USBSERIAL.print("txLineInLevel: ");
USBSERIAL.println(c->txLineInLevel);
break;
case 'v':
case 'V':
// volume
if (set_value) {
c->txLineInVol = value;
updateTxLineIn();
}
USBSERIAL.print("txLineInVol: ");
USBSERIAL.println(c->txLineInVol);
break;
case 'c':
case 'C':
// calibration
if (set_value) {
c->txLineInCal = value;
updateTxLineIn();
}
USBSERIAL.print("txLineInCal: ");
USBSERIAL.println(c->txLineInCal);
break;
}
break;
case 'u':
case 'U':
// USB input
switch(parm) {
case 'v':
case 'V':
// volume
if (set_value) {
c->txUSBInVol = value;
updateTxUSBIn();
}
USBSERIAL.print("txUSBInVol: ");
USBSERIAL.println(c->txUSBInVol);
break;
case 'c':
case 'C':
// calibration
if (set_value) {
c->txUSBInCal = value;
updateTxUSBIn();
}
USBSERIAL.print("txUSBInCal: ");
USBSERIAL.println(c->txUSBInCal);
break;
}
break;
case 'r':
case 'R':
// Rig output
switch(parm) {
case 'l':
case 'L':
// level
if (set_value) {
c->txRigOutLevel = int(value);
updateTxRigOut();
}
USBSERIAL.print("txRigOutLevel: ");
USBSERIAL.println(c->txRigOutLevel);
break;
case 'c':
case 'C':
// calibration
if (set_value) {
c->txRigOutCal = value;
updateTxRigOut();
}
USBSERIAL.print("txRigOutCal: ");
USBSERIAL.println(c->txRigOutCal);
break;
}
break;
}
break;
}
}
int lpFilter[5];
int hpFilter[5];
void audioSSBFilter()
{
// calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*);
calcBiquad(FILTER_LOPASS, 3300, 0, 0.707, 524288, 44100, lpFilter);
calcBiquad(FILTER_HIPASS, 100, 0, 0.707, 524288, 44100, hpFilter);
audioCtrl.eqFilter(0, lpFilter);
audioCtrl.eqFilter(1, hpFilter);
audioCtrl.eqFilter(2, lpFilter);
audioCtrl.eqFilter(3, hpFilter);
audioCtrl.eqFilter(4, lpFilter);
audioCtrl.eqFilter(5, hpFilter);
}
void audioCWFilter()
{
// calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*);
calcBiquad(FILTER_LOPASS, 1300, 0, 0.707, 524288, 44100, lpFilter);
calcBiquad(FILTER_HIPASS, 100, 0, 0.707, 524288, 44100, hpFilter);
audioCtrl.eqFilter(0, lpFilter);
audioCtrl.eqFilter(1, hpFilter);
audioCtrl.eqFilter(2, lpFilter);
audioCtrl.eqFilter(3, hpFilter);
audioCtrl.eqFilter(4, lpFilter);
audioCtrl.eqFilter(5, hpFilter);
}
//======================================================================
// audioDigiFilter()
// Create a very wide filter for digital modes... wider than the uBITX
// needs, but just want to make sure we leave the full audio bandwidth
// open for digimodes, while ensuring we've cut down any extraneous
// noise outside the normal band.
//======================================================================
void audioDigiFilter()
{
// calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*);
calcBiquad(FILTER_LOPASS, 5000, 0, 0.707, 524288, 44100, lpFilter);
calcBiquad(FILTER_HIPASS, 100, 0, 0.707, 524288, 44100, hpFilter);
audioCtrl.eqFilter(0, lpFilter);
audioCtrl.eqFilter(1, hpFilter);
audioCtrl.eqFilter(2, lpFilter);
audioCtrl.eqFilter(3, hpFilter);
audioCtrl.eqFilter(4, lpFilter);
audioCtrl.eqFilter(5, hpFilter);
}
*/
int eqFilter1[5];
void audioEqualizer()

View File

@ -10,7 +10,7 @@ IOPMessage inBuf; // input message buffer
IOPMessage outBuf; // output message buffer
extern CATSwitch catPTT;
extern Rig rig;
extern basic_rig rig;
int received_mode = 0;
@ -57,27 +57,21 @@ void processIOPCommand(IOPMessage const& m)
if (m.len < 1) {
return;
} else {
rig.switchMode(rig_mode(m.data[0]));
rig.set_rig_mode(static_cast<rig_mode>(m.data[0]));
#if defined(DEBUG)
switch(rig.modeNum()) {
case cwr:
USBDEBUG("new mode - CWR");
break;
case cw:
switch(rig.get_rig_mode()) {
case rig_mode::cw:
USBDEBUG("new mode - CW");
break;
case lsb:
USBDEBUG("new mode - LSB");
case rig_mode::ssb:
USBDEBUG("new mode - SSB");
break;
case usb:
USBDEBUG("new mode - USB");
break;
case dig:
case rig_mode::digi:
USBDEBUG("new mode - DIG");
break;
default:
char errormessage[32];
sprintf(errormessage, "unknown mode command - %3d", rig.modeNum());
sprintf(errormessage, "unknown mode command - %3d", rig.get_rig_mode());
USBDEBUG("mode command not recognized");
}
#endif

View File

@ -120,13 +120,12 @@ class RigConfig {
AudioConfig audio;
// mode configuration
ssb_config ssb;
dig_config dig;
cw_config cw;
ssb_config ssb;
digi_config digi;
cw_config cw;
// General rig configuration entries.
rig_mode numModes = num_rig_modes;
rig_mode startMode = lsb;
rig_mode mode = rig_mode::ssb;
};
extern RigConfig rigConfig;

View File

@ -13,9 +13,6 @@
//#include <vector>
#include <initializer_list>
#include "rig.h"
#include "tx_audio_proc.h"
extern SpeechCompressor speechCompressor; // This should be somewhere else.
// 16 characters on display
const int MAX_TEXT_LEN = 16;
@ -211,11 +208,9 @@ class Parm_float : public Config_parm<float> {
//======================================================================
const char modeID[] = {'s', 'S', 'c', 'C', 'd', 'D', 't', 'T'};
const char* const filterID[num_rig_modes][num_rx_filters] = {
{"2.8", "2.4", "1.8"}, // LSB
{"2.8", "2.4", "1.8"}, // USB
const char* const filterID[static_cast<int>(rig_mode::count)][static_cast<int>(rx_filter::count)] = {
{"2.8", "2.4", "1.8"}, // SSB
{"1.0", "500", "250"}, // CW
{"1.0", "500", "250"}, // CWR
{"2.8", "2.4", "500"}, // DIG
};
@ -226,7 +221,7 @@ const char* const filterID[num_rig_modes][num_rx_filters] = {
class Main_menu : public Menu_item {
public:
Main_menu(Rig& rig): menu_title("Main Menu"), rig(rig), adjust_tx(false), comp_on(false) {}
Main_menu(basic_rig& rig): menu_title("Main Menu"), rig_(rig), adjust_tx(false) {}
virtual const Menu_string& title() const {
return menu_title;
@ -240,33 +235,12 @@ class Main_menu : public Menu_item {
char text[max_text_len+1];
sprintf(text, "%1cR:%3s %1cT:%3s ",
adjust_tx ? ' ' : menu_selection_char,
filterID[rig.modeNum()][rig.filterNum()],
filterID[static_cast<size_t>(rig_.get_rig_mode())][static_cast<size_t>(rig_.get_rx_filter())],
adjust_tx ? menu_selection_char : ' ',
rig.isSSBMode() && comp_on ? "CMP" : " ");
rig_.is_ssb_mode() && rig_.config().ssb.comp.enabled ? "CMP" : " ");
outstr.assign(text);
}
/*
virtual void update() {
sprintf(_text0, "%1cR:%3s %1cT:%3s ",
_adjust_tx ? ' ' : MENU_SELECTED_CHAR,
filterID[_rig.modeNum()][_rig.filterNum()],
_adjust_tx ? MENU_SELECTED_CHAR : ' ',
_rig.isSSBMode() && _comp_on ? "CMP" : " ");
if ((strcmp(_text0, _text1) != 0) || _dirty) {
if (_visible) {
sendIOPMenuDisplay(_text0);
USBDEBUG("updating menu:");
USBDEBUG(_text0);
} else {
sendIOPMenuInactive();
USBDEBUG("deactivating menu");
}
_dirty = false;
strncpy(_text1, _text0, MAX_TEXT_LEN);
}
}
*/
virtual Menu_item* select() {
adjust_tx = !adjust_tx;
return this;
@ -282,79 +256,40 @@ class Main_menu : public Menu_item {
virtual Menu_item* prev() {
if (adjust_tx) {
if (rig.isSSBMode()) {
comp_on = !comp_on;
if (comp_on)
speechCompressor.enable();
if (rig_.is_ssb_mode()) {
rig_.config().ssb.comp.enabled = !rig_.config().ssb.comp.enabled;
if (rig_.config().ssb.comp.enabled)
rig_.enable_comp();
else
speechCompressor.disable();
rig_.disable_comp();
}
} else {
rig.switchRxFilter(true);
rig_.prev_rx_filter();
}
return this;
}
virtual Menu_item* next() {
if (adjust_tx) {
if (rig.isSSBMode()) {
comp_on = !comp_on;
if (comp_on)
speechCompressor.enable();
if (rig_.is_ssb_mode()) {
rig_.config().ssb.comp.enabled = !rig_.config().ssb.comp.enabled;
if (rig_.config().ssb.comp.enabled)
rig_.enable_comp();
else
speechCompressor.disable();
rig_.disable_comp();
}
} else {
rig.switchRxFilter();
rig_.next_rx_filter();
}
return this;
}
private:
Menu_string menu_title;
Rig& rig;
basic_rig& rig_;
bool adjust_tx;
bool comp_on;
};
/*
public class MenuItem {
public:
MenuItem(bool active = true, int timeout = 0): _active(active), _timeout(timeout), _elapsed(0) {}
void update() {
if ((_timeout > 0) && (_elapsed > _timeout)) {
_active = false;
}
}
inline void activate() { _active = true; _elapsed = 0; }
inline void deactivate() { _active = false; }
virtual MenuItem* accept();
virtual MenuItem* reject();
virtual MenuItem* next();
virtual MenuItem* prev();
private:
bool _active;
int _timeout;
elapsedMillis _elapsed;
};
public class SSBMenu {
public:
private:
};
public class DigiMenu {
public:
private:
}
public class CWMenu {
public:
private:
};
*/
extern const Menu_item* audio_config_menu;
#endif

View File

@ -8,143 +8,80 @@
#include <iopcomm.h>
#include "audio.h"
#include "RigMode.h"
//#include "menu.h"
//======================================================================
// Rig class
// basic_rig
//======================================================================
class Rig {
class basic_rig {
public:
//--------------------------------------------------------------------
// Constructor/destructor.
//--------------------------------------------------------------------
Rig(RigConfig& c, RigAudio& a): _config(c), _audio(a), _filter(wide)
{
_modes = new IMode*[c.numModes];
_modesLen = c.numModes;
_modesIndex = c.startMode;
basic_rig(RigConfig& c, RigAudio& a) :
config_(c), audio_(a),
bpf_(),
comp_(&config_.ssb.comp),
ssb_ (config_.ssb, audio_, bpf_, comp_),
cw_ (config_.cw, audio_, bpf_),
digi_(config_.digi, audio_, bpf_) { set_rig_mode(config_.mode); }
// for (int i = 0; i < 16; i++) { _modeText[i] = ' '; }
// _modeText[16] = '\0';
/* _modes[RIG_MODE_LSB] = new SSBMode(c.lsb, a);
_modes[RIG_MODE_USB] = new SSBMode(c.usb, a);
_modes[RIG_MODE_CWL] = new CWMode(c.cwl, a);
_modes[RIG_MODE_CWU] = new CWMode(c.cwu, a);
_modes[RIG_MODE_DGL] = new DGTMode(c.dgl, a);
_modes[RIG_MODE_DGU] = new DGTMode(c.dgu, a);
_modes[RIG_MODE_TTL] = new TTMode(c.ttl, a);
_modes[RIG_MODE_TTU] = new TTMode(c.ttu, a);*/
/*
_rxFilters = new (IFilter*)[num_rx_filters];
_rxFiltersLen = num_rx_filters;
_rxFiltersIndex = 0; // need to get default filter from current mode...
_rxFilters[wide] = mode()->filterWide();
_rxFilters[medium] = mode()->filterMedium();
_rxFilters[narrow] = mode()->filterNarrow();
*/
}
~Rig()
{
for (unsigned i = 0; i < _modesLen; i++) {
delete _modes[i];
}
delete _modes;
}
void init() {
switchRxFilter(_filter);
}
void init() {}
RigConfig& config() { return config_; }
//--------------------------------------------------------------------
// Mode control.
//--------------------------------------------------------------------
/*
const char* modeText() {
sprintf(_modeText, "%1c- %6s %6s", modeID[_modesIndex],
mode()->rxInfo(), mode()->txInfo());
return _modeText;
}
*/
inline bool isSSBMode() const { return (_modesIndex == usb || _modesIndex == lsb); }
// inline bool isUSBMode() const { return (_modesIndex == usb); }
// inline bool isLSBMode() const { return (_modesIndex == lsb); }
inline bool isDIGMode() const { return (_modesIndex == dig); }
inline bool isCWMode() const { return (_modesIndex == cw || _modesIndex == cwr); }
// inline bool isCWUMode() const { return (_modesIndex == RIG_MODE_CWU); }
// inline bool isCWLMode() const { return (_modesIndex == RIG_MODE_CWL); }
// Assign a pointer to a mode object. Returns true if successful, false otherwise.
bool addNewMode(rig_mode i, IMode* mode) {
if (i > _modesLen) {
return false;
} else {
_modes[i] = mode;
return true;
}
}
// Returns a pointer to the current mode.
inline IMode* mode() const {
return _modes[_modesIndex];
}
inline bool is_ssb_mode() const { return (config_.mode == rig_mode::ssb ); }
inline bool is_digi_mode() const { return (config_.mode == rig_mode::digi); }
inline bool is_cw_mode() const { return (config_.mode == rig_mode::cw ); }
// Returns the array index of the current mode.
inline rig_mode modeNum() const {
return _modesIndex;
}
/* // Returns a pointer to the specified mode.
inline IMode* mode(RigMode m) const {
return _modes[m];
}*/
// Switch to the mode specified by the provided index. Returns a
// pointer to the new mode.
IMode* switchMode(rig_mode i) {
// Switch to the specified mode. Returns a pointer to the new mode.
basic_mode* set_rig_mode(rig_mode m) {
// exit the previous mode
mode()->exit(); // NOTE: This could currently occur during TX, which is NOT desirable.
current_mode_->exit(); // NOTE: This could currently occur during TX, which is NOT desirable.
// select the new mode
_modesIndex = rig_mode(i % _modesLen);
config_.mode = m;
switch(config_.mode) {
case rig_mode::ssb:
current_mode_ = &ssb_;
break;
case rig_mode::cw:
current_mode_ = &cw_;
break;
case rig_mode::digi:
current_mode_ = &digi_;
break;
}
//enter the new mode
mode()->enter();
current_mode_->enter();
// return a pointer to the new mode
return mode();
return current_mode_;
}
// Advance to the next (or previous) mode. Returns a pointer to the
// new mode.
IMode* switchMode(bool prev=false) {
// Returns the rig_mode (enum) of the current mode object.
inline rig_mode get_rig_mode() const { return config_.mode; }
// exit the previous mode
mode()->exit();
// select the new mode
if (prev) {
_modesIndex = rig_mode(_modesIndex > 0 ? _modesIndex - 1 : _modesLen - 1);
} else {
_modesIndex = rig_mode((_modesIndex + 1) % _modesLen);
}
// enter the new mode
mode()->enter();
// return a pointer to the new mode
return mode();
}
// Returns a pointer to the current mode object.
inline basic_mode* mode() const { return current_mode_; }
//--------------------------------------------------------------------
// Transmit/Receive (T/R) control.
//--------------------------------------------------------------------
inline bool isTx() const { return mode()->isTx(); }
inline bool isRx() const { return mode()->isRx(); }
inline bool is_tx() const { return mode()->is_tx(); }
inline bool is_rx() const { return mode()->is_rx(); }
// Enter the transmit state. This is delegated to the mode.
inline void tx() { mode()->tx(); }
@ -156,178 +93,144 @@ class Rig {
// Transmit processor control.
//--------------------------------------------------------------------
void switchProcessor(bool prev=false) {
inline void enable_comp() {
if (is_ssb_mode()) ((ssb_mode*)mode())->enable_comp();
}
inline void disable_comp() {
if (is_ssb_mode()) ((ssb_mode*)mode())->disable_comp();
}
//--------------------------------------------------------------------
// RX filter control.
//--------------------------------------------------------------------
inline void setWideRxFilter() {
_filter = wide;
mode()->setWideRxFilter();
USBDEBUG("selected wide RX filter");
}
// Set the RX filter. This is delegated to the mode.
inline void set_rx_filter(rx_filter f) { mode()->set_rx_filter(f); }
inline void setMediumRxFilter() {
_filter = medium;
mode()->setMediumRxFilter();
USBDEBUG("selected medium RX filter");
}
// Returns the rx_filter (enum) of the RX filter currently being used.
inline rx_filter get_rx_filter() const { return mode()->config().filter; }
inline void setNarrowRxFilter() {
_filter = narrow;
mode()->setNarrowRxFilter();
USBDEBUG("selected narrow RX filter");
}
void switchRxFilter(rx_filter f) {
switch(f) {
case wide:
setWideRxFilter();
void next_rx_filter() {
switch(mode()->config().filter) {
case rx_filter::wide:
set_rx_filter(rx_filter::medium);
break;
case medium:
setMediumRxFilter();
case rx_filter::medium:
set_rx_filter(rx_filter::narrow);
break;
case narrow:
setNarrowRxFilter();
case rx_filter::narrow:
set_rx_filter(rx_filter::wide);
break;
}
}
void switchRxFilter(bool prev=false) {
rx_filter f;
if (prev) {
f = rx_filter(_filter > 0 ? _filter - 1 : num_rx_filters - 1);
} else {
f = rx_filter((_filter + 1) % num_rx_filters);
void prev_rx_filter() {
switch(mode()->config().filter) {
case rx_filter::wide:
set_rx_filter(rx_filter::narrow);
break;
case rx_filter::medium:
set_rx_filter(rx_filter::wide);
break;
case rx_filter::narrow:
set_rx_filter(rx_filter::medium);
break;
}
switchRxFilter(f);
}
// Returns the array index of the current mode.
inline rx_filter filterNum() const {
return _filter;
}
/*
// Returns a pointer to the current RX filter.
IFilter* rxFilter() {
return _rxFilters[_rxFiltersIndex];
}
IFilter* switchRxFilter(bool prev=false) {
if (prev) {
_rxFiltersIndex--;
} else {
_rxFiltersIndex++;
}
_rxFiltersIndex %= _rxFiltersLen;
return _rxFiltersList[_rxFiltersIndex];
}
IFilter* switchRxFilterWide() {
}
IFilter* switchFilterMedium() {
}
IFilter* switchFilterNarrow() {
}
*/
//--------------------------------------------------------------------
// Audio output control.
//--------------------------------------------------------------------
inline void muteSpkrOut() const {
_audio.muteSpkrOut();
audio_.muteSpkrOut();
}
inline void unmuteSpkrOut() const {
_audio.unmuteSpkrOut();
audio_.unmuteSpkrOut();
}
inline void muteLineOut() const {
_audio.muteLineOut();
audio_.muteLineOut();
}
inline void unmuteLineOut() const {
_audio.unmuteLineOut();
audio_.unmuteLineOut();
}
inline void muteUSBOut() const {
_audio.muteUSBOut();
audio_.muteUSBOut();
}
inline void unmuteUSBOut() const {
_audio.unmuteUSBOut();
audio_.unmuteUSBOut();
}
//--------------------------------------------------------------------
// Audio input control.
//--------------------------------------------------------------------
inline void muteAllTx() const {
_audio.muteAllTx();
audio_.muteAllTx();
}
inline void muteMicIn() const {
_audio.muteMicIn();
audio_.muteMicIn();
}
inline void unmuteMicIn() const {
_audio.unmuteMicIn();
audio_.unmuteMicIn();
}
inline void muteLineIn() const {
_audio.muteLineIn();
audio_.muteLineIn();
}
inline void unmuteLineIn() const {
_audio.unmuteLineIn();
audio_.unmuteLineIn();
}
inline void muteUSBIn() const {
_audio.muteUSBIn();
audio_.muteUSBIn();
}
inline void unmuteUSBIn() const {
_audio.unmuteUSBOut();
audio_.unmuteUSBOut();
}
inline void muteTTIn() const {
_audio.muteTTIn();
audio_.muteTTIn();
}
inline void unmuteTTIn() const {
_audio.unmuteTTIn();
audio_.unmuteTTIn();
}
// Update the rig state. This should be called once each time through
// the main loop.
void update()
{
comp_.update(); // It checks if it's enabled on its own.
}
private:
RigConfig& _config;
RigAudio& _audio;
RigConfig& config_;
RigAudio& audio_;
IMode** _modes;
rig_mode _modesLen;
rig_mode _modesIndex;
bp_filter bpf_;
speech_comp comp_;
rx_filter _filter;
ssb_mode ssb_;
cw_mode cw_;
digi_mode digi_;
// char _modeText[17];
/*
IFilter** _rxFilters;
uint8_t _rxFiltersLen;
uint8_t _rxFiltersIndex;
*/
basic_mode* current_mode_;
};
#endif

View File

@ -1,46 +0,0 @@
//======================================================================
// tx_audio_proc.h
//
// Classes/functions for processing transmit audio.
//======================================================================
#ifndef __tx_audio_proc_h__
#define __tx_audio_proc_h__
#include <Audio.h>
#include <effect_compressor_fb.h>
class IAudioProcessor
{
public:
virtual ~IAudioProcessor() {}
virtual bool isEnabled() const = 0;
virtual void enable() = 0;
virtual void disable() = 0;
virtual void update() = 0;
};
class SpeechCompressor : public IAudioProcessor
{
public:
SpeechCompressor(AudioEffectCompressor&, AudioAmplifier&, AudioAnalyzeRMS&);
//void config(AudioEffectCompressor*, AudioAnalyzeRMS*);
virtual bool isEnabled() const;
virtual void enable();
virtual void disable();
virtual void update();
private:
AudioEffectCompressor& _compress;
AudioAmplifier& _amp;
AudioAnalyzeRMS& _rms;
float _env = 0.0;
float _alpha = 0.8;
bool _enabled = false;
};
#endif
//======================================================================
// EOF
//======================================================================

View File

@ -1,53 +0,0 @@
//======================================================================
// tx_audio_proc.ino
//
// Classes/functions for processing transmit audio.
//======================================================================
#include "tx_audio_proc.h"
SpeechCompressor::SpeechCompressor(AudioEffectCompressor& comp, AudioAmplifier& amp, AudioAnalyzeRMS& rms):
_compress(comp), _amp(amp), _rms(rms)
{
}
//void SpeechCompressor::config(AudioEffectCompressor* comp, AudioAnalyzeRMS* rms)
//{
// _compress = comp;
// _rms = rms;
//}
bool SpeechCompressor::isEnabled() const
{
return _enabled;
}
void SpeechCompressor::enable()
{
_enabled = true;
_compress.begin(1, 0.1, 20); // Need to make configurable
_amp.gain(2.0);
}
void SpeechCompressor::disable()
{
_enabled = false;
_compress.disable();
_amp.gain(1.0);
}
// Speech compressor code based on post by 'hyperdyne': https://forum.pjrc.com/threads/36245-Changing-Pitch-of-Voice
void SpeechCompressor::update()
{
float rms_cur;
if (_enabled && _rms.available()) {
rms_cur = _rms.read();
_env = rms_cur + (_alpha * (_env - rms_cur));
_compress.update_pwr(_env);
}
}
//======================================================================
// EOF
//======================================================================

View File

@ -16,13 +16,7 @@ Keyer keyer{15, 3.0}; // NOTE: make configurable
RigConfig rigConfig;
RigAudio rigAudio{rigConfig.audio};
Rig rig{rigConfig, rigAudio};
BPFilter rxFilter{300, 3100, false};
SSBMode ssbMode{rigConfig.ssb, rigAudio, rxFilter};
DGTMode digMode{rigConfig.dig, rigAudio, rxFilter};
CWMode cwMode {rigConfig.cw, rigAudio, rxFilter};
basic_rig rig{rigConfig, rigAudio};
CATSwitch catPTT;
//MicSwitch micPTTHelper;
@ -54,16 +48,6 @@ void setup() {
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(lsb, &ssbMode);
rig.addNewMode(usb, &ssbMode);
rig.addNewMode(cw, &cwMode);
rig.addNewMode(cwr, &cwMode);
rig.addNewMode(dig, &digMode);
initKeyLine();
rigAudio.init();
@ -78,14 +62,6 @@ void setup() {
rig.init();
USBDEBUG("setup completed");
// audioInit();
/*
#if defined(FACTORY_CALIBRATION)
setRigMode(RIG_MODE_TEST);
#else
setRigMode(RIG_MODE_SSB);
#endif
*/
}
//======================================================================
@ -118,13 +94,13 @@ void loop()
frameCounter++;
if (rig.isCWMode()) {
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.isRx()) {
if (rig.is_rx()) {
USBDEBUG("entered TX via paddles");
rig.tx();
}
@ -154,21 +130,21 @@ void loop()
rig.update();
oldRigMode = rig.modeNum();
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.isSSBMode());
micPTT.update(rig.mode(), !rig.isDIGMode());
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.isSSBMode());
linePTT.update(rig.mode(), !rig.isDIGMode());
linePTT.setSSBMode(rig.is_ssb_mode());
linePTT.update(rig.mode(), !rig.is_digi_mode());
serviceCAT();
@ -237,9 +213,7 @@ void loop()
USBDEBUG("updated main menu");
}
// update the speech compressor. Really should do this elsewhere.
if (speechCompressor.isEnabled())
speechCompressor.update();
rig.update();
if (frameMillis > 5000) {
#if defined(DEBUG)