Added missing files to commit.

This commit is contained in:
Rob French 2020-05-25 23:11:36 -05:00
parent 564c35f397
commit 322909c6f2
5 changed files with 917 additions and 0 deletions

307
ubitx_iop/RigMode.h Normal file
View File

@ -0,0 +1,307 @@
//======================================================================
// RigMode.h
//======================================================================
#ifndef __RigMode_h__
#define __RigMode_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
//
// Interface to a rig mode (SSB, CW, etc.).
//======================================================================
class IMode {
public:
IMode(IConfig& c, RigAudio& a):
_config(c), _audio(a), _active(false), _transmitting(false)
{
}
virtual ~IMode() {}
inline IConfig& config() { return _config; }
inline RigAudio& audio() { return _audio; }
// 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;
// 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;
// Called when transmitting.
virtual void onTx() = 0;
// Called when receiving.
virtual void onRx() = 0;
inline void enter() {
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();
}
}
inline void exit() {
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();
}
}
inline bool isActive() { return _active; }
inline bool isInactive() { return !_active; }
inline void tx() {
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();
}
}
inline void rx() {
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();
}
}
inline bool isTx() const { return _transmitting; }
inline bool isRx() const { return !_transmitting; }
private:
IConfig& _config;
RigAudio& _audio;
bool _active;
bool _transmitting;
};
//======================================================================
// SSBMode
//======================================================================
class SSBMode : public IMode
{
public:
SSBMode(IConfig& c, RigAudio& a, bool default_mic=true):
IMode(c, a), _use_mic(default_mic)
{
}
virtual void onEntry()
{
audio().unmuteRx();
audio().muteAllTx();
USBDEBUG("SSB mode entered");
}
virtual void onExit() {
audio().muteAllTx();
audio().muteRx();
USBDEBUG("SSB mode exited");
}
virtual void onTx()
{
audio().muteRx();
if (_use_mic) {
audio().unmuteMicIn();
} else {
audio().unmuteLineIn();
}
USBDEBUG("SSB mode transmitting");
}
virtual void onRx()
{
if (_use_mic) {
audio().muteMicIn();
} else {
audio().muteLineIn();
}
audio().unmuteRx();
USBDEBUG("SSB mode receiving");
}
void setMicIn()
{
if (isRx()) {
// can't switch inputs while already transmitting
_use_mic = true;
}
USBDEBUG("SSB mode - Mic In set");
}
void setLineIn()
{
if (isRx()) {
// can't switch inputs while already transmitting
_use_mic = false;
}
USBDEBUG("SSB mode - Line In set");
}
private:
bool _use_mic;
};
//======================================================================
// DGTMode
//======================================================================
class DGTMode : public IMode
{
public:
DGTMode(IConfig& c, RigAudio& a):
IMode(c, a)
{
}
virtual void onEntry()
{
audio().unmuteRx();
audio().muteAllTx();
USBDEBUG("DGT mode entered");
}
virtual void onExit() {
audio().muteAllTx();
audio().muteRx();
USBDEBUG("DGT mode exited");
}
virtual void onTx()
{
audio().muteRx();
audio().unmuteUSBIn();
USBDEBUG("DGT mode transmitting");
}
virtual void onRx()
{
audio().muteUSBIn();
audio().unmuteRx();
USBDEBUG("DGT mode receiving");
}
};
//======================================================================
// CWMode
//======================================================================
class CWMode : public IMode
{
public:
CWMode(IConfig& c, RigAudio& a):
IMode(c, a)
{
}
virtual void onEntry()
{
audio().unmuteRx();
audio().muteAllTx();
USBDEBUG("CW mode entered");
}
virtual void onExit() {
audio().muteAllTx();
audio().muteRx();
USBDEBUG("CW mode exited");
}
virtual void onTx()
{
// Currently not muting Rx, since the uBITX produces it's own
// sidetone... but I'm probably going to replace that with a S/W-
// generated sidetone.
USBDEBUG("CW mode transmitting");
}
virtual void onRx()
{
USBDEBUG("CW mode receiving");
}
};
//======================================================================
// TTMode
//======================================================================
class TTMode : public IMode
{
public:
TTMode(IConfig& c, RigAudio& a):
IMode(c, a)
{
}
virtual void onEntry()
{
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");
}
};
#endif
//======================================================================
// EOF
//======================================================================

249
ubitx_iop/TxSwitch.h Normal file
View File

@ -0,0 +1,249 @@
//======================================================================
// TxSwitch.h
//======================================================================
#ifndef __TxSwitch_h__
#define __TxSwitch_h__
#include <Bounce2.h>
#define BOUNCE_WITH_PROMPT_DETECTION
#include "ubitx_iop.h"
#include "rig.h"
#define MIC_PTT_PIN 21
#define LINE_PTT_PIN 20
//----------------------------------------------------------------------
// ITxSwitch
//
// Interface for transmit (PTT, Key) switches. onPress() is called
// before transmission begins, and should return true if transmission
// should start. onRelease() is called before transmission ends, and
// should return true if transmission should in fact end.
//----------------------------------------------------------------------
class ITxSwitch
{
public:
virtual ~ITxSwitch() {}
// Called before beginning transmit; if false, transmit aborts before starting.
virtual bool onPress(IMode* m) = 0;
// Called before stopping tranmit; if false, transmit continues.
virtual bool onRelease(IMode* m) = 0;
void press(IMode* m, bool output_enable=true) {
if (onPress(m)) {
USBDEBUG("PTT pressed");
m->tx();
if (output_enable) {
setKeyDown(); // NOTE: could still make this more configurable...
}
}
}
void release(IMode* m, bool output_enable=true) {
if (onRelease(m)) {
USBDEBUG("PTT released");
if (output_enable) {
setKeyUp(); // NOTE: could still make this more configurable...
}
m->rx();
}
}
};
//----------------------------------------------------------------------
// CATSwitch
//
// Implementation of the ITxSwitch interface for the CAT control. In
// general, CAT cannot override any existing transmission, and cannot
// terminate an existing transmission.
//----------------------------------------------------------------------
class CATSwitch : public ITxSwitch
{
public:
CATSwitch(): _transmitting(false) {}
virtual bool onPress(IMode* m) {
// If another transmission is already occuring, abort... CAT can't
// interrupt transmissions already ongoing.
if (m->isRx()) {
USBDEBUG("CAT PTT pressed");
_transmitting = true;
return true;
} else {
return false;
}
}
virtual bool onRelease(IMode* 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
// transmitting because of CAT.
if (_transmitting) {
USBDEBUG("CAT PTT released");
_transmitting = false;
return true;
} else {
return false;
}
}
private:
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
//
// Class used to implement the physical transmit switches (i.e. the
// Mic and Line input PTTs which are connected to GPIO pins). Takes
// an object implementing the ITxSwitch interface, as well as info for
// setting up a debounced pin.
//----------------------------------------------------------------------
class GPIOSwitch : public ITxSwitch
{
public:
GPIOSwitch(bool is_mic, int pin, int msec=25): _is_mic(false), _ssb_mode(false), _bounce() {
_bounce.attach(pin, INPUT_PULLUP);
_bounce.interval(msec);
}
inline void setSSBMode(bool flag) { _ssb_mode = flag; }
virtual bool onPress(IMode* m) {
if (m->isRx()) {
if (_ssb_mode) {
if (_is_mic) {
USBDEBUG("Mic PTT pressed");
((SSBMode*)m)->setMicIn();
} else {
USBDEBUG("Line PTT pressed");
((SSBMode*)m)->setLineIn();
}
}
return true;
} else {
return false;
}
}
virtual bool onRelease(IMode* m) {
if (m->isTx()) {
return true;
} else {
return false;
}
}
void update(IMode* m, bool output_enable=true) {
_bounce.update();
if (_bounce.fell()) {
press(m, output_enable);
} else if (_bounce.rose()) {
release(m, output_enable);
}
}
private:
bool _is_mic;
bool _ssb_mode;
Bounce _bounce;
};
#endif
//======================================================================
// EOF
//======================================================================

264
ubitx_iop/rig.h Normal file
View File

@ -0,0 +1,264 @@
//======================================================================
// rig.h
//======================================================================
#ifndef __rig_h__
#define __rig_h__
#include <iopcomm.h>
#include "audio.h"
#include "RigMode.h"
//======================================================================
// Rig class
//======================================================================
class Rig {
public:
//--------------------------------------------------------------------
// Constructor/destructor.
//--------------------------------------------------------------------
Rig(RigConfig& c, RigAudio& a): _config(c), _audio(a)
{
_modes = new IMode*[NUM_RIG_MODES];
_modesLen = NUM_RIG_MODES;
_modesIndex = c.mode;
_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[RX_FILTER_WIDE] = mode()->filterWide();
_rxFilters[RX_FILTER_MEDIUM] = mode()->filterMedium();
_rxFilters[RX_FILTER_NARROW] = mode()->filterNarrow();
*/
}
~Rig()
{
for (int i = 0; i < _modesLen; i++) {
delete _modes[i];
}
delete _modes;
}
//--------------------------------------------------------------------
// Mode control.
//--------------------------------------------------------------------
inline bool isSSBMode() const { return (_modesIndex == RIG_MODE_USB || _modesIndex == RIG_MODE_LSB); }
inline bool isUSBMode() const { return (_modesIndex == RIG_MODE_USB); }
inline bool isLSBMode() const { return (_modesIndex == RIG_MODE_LSB); }
inline bool isDGTMode() const { return (_modesIndex == RIG_MODE_DGU || _modesIndex == RIG_MODE_DGL); }
inline bool isDGUMode() const { return (_modesIndex == RIG_MODE_DGU); }
inline bool isDGLMode() const { return (_modesIndex == RIG_MODE_DGL); }
inline bool isCWMode() const { return (_modesIndex == RIG_MODE_CWU || _modesIndex == RIG_MODE_CWL); }
inline bool isCWUMode() const { return (_modesIndex == RIG_MODE_CWU); }
inline bool isCWLMode() const { return (_modesIndex == RIG_MODE_CWL); }
inline bool isTTMode() const { return (_modesIndex == RIG_MODE_TTU || _modesIndex == RIG_MODE_TTL); }
inline bool isTTUMode() const { return (_modesIndex == RIG_MODE_TTU); }
inline bool isTTLMode() const { return (_modesIndex == RIG_MODE_TTL); }
// Returns a pointer to the current mode.
inline IMode* mode() const {
return _modes[_modesIndex];
}
inline RigMode modeNum() const {
return RigMode(_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(RigMode i) {
// exit the previous mode
mode()->exit(); // NOTE: This could currently occur during TX, which is NOT desirable.
// select the new mode
_modesIndex = i % _modesLen; // do I need the modulo?
//enter the new mode
mode()->enter();
// return a pointer to the new mode
return mode();
}
// Advance to the next (or previous) mode. Returns a pointer to the
// new mode.
IMode* switchMode(bool prev=false) {
// exit the previous mode
mode()->exit();
// select the new mode
if (prev) {
_modesIndex--;
} else {
_modesIndex++;
}
_modesIndex %= _modesLen;
// enter the new mode
mode()->enter();
// return a pointer to the new mode
return mode();
}
//--------------------------------------------------------------------
// Transmit/Receive (T/R) control.
//--------------------------------------------------------------------
inline bool isTx() const { return mode()->isTx(); }
inline bool isRx() const { return mode()->isRx(); }
// Enter the transmit state. This is delegated to the mode.
inline void tx() { mode()->tx(); }
// Enter the receive state. This is delegated to the mode.
inline void rx() { mode()->rx(); }
//--------------------------------------------------------------------
// Transmit processor control.
//--------------------------------------------------------------------
void switchProcessor(bool prev=false) {
}
//--------------------------------------------------------------------
// RX filter control.
//--------------------------------------------------------------------
/*
// 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();
}
inline void unmuteSpkrOut() const {
_audio.unmuteSpkrOut();
}
inline void muteLineOut() const {
_audio.muteLineOut();
}
inline void unmuteLineOut() const {
_audio.unmuteLineOut();
}
inline void muteUSBOut() const {
_audio.muteUSBOut();
}
inline void unmuteUSBOut() const {
_audio.unmuteUSBOut();
}
// Audio input control.
inline void muteAllTx() const {
_audio.muteAllTx();
}
inline void muteMicIn() const {
_audio.muteMicIn();
}
inline void unmuteMicIn() const {
_audio.unmuteMicIn();
}
inline void muteLineIn() const {
_audio.muteLineIn();
}
inline void unmuteLineIn() const {
_audio.unmuteLineIn();
}
inline void muteUSBIn() const {
_audio.muteUSBIn();
}
inline void unmuteUSBIn() const {
_audio.unmuteUSBOut();
}
inline void muteTTIn() const {
_audio.muteTTIn();
}
inline void unmuteTTIn() const {
_audio.unmuteTTIn();
}
// Update the rig state. This should be called once each time through
// the main loop.
void update()
{
}
private:
RigConfig& _config;
RigAudio& _audio;
IMode** _modes;
uint8_t _modesLen;
uint8_t _modesIndex;
/*
IFilter** _rxFilters;
uint8_t _rxFiltersLen;
uint8_t _rxFiltersIndex;
*/
};
#endif
//======================================================================
// EOF
//======================================================================

46
ubitx_iop/tx_audio_proc.h Normal file
View File

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

@ -0,0 +1,51 @@
//======================================================================
// 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.5, 4); // Need to make configurable
}
void SpeechCompressor::disable()
{
_enabled = false;
_compress.disable();
}
// 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
//======================================================================