About to make a bunch of changes (really not all keyer related), so
committing for safety...
This commit is contained in:
parent
a039740466
commit
e9d021835a
123
ubitx_iop/cat.h
123
ubitx_iop/cat.h
|
@ -5,11 +5,134 @@
|
||||||
#ifndef __iop_cat_h__
|
#ifndef __iop_cat_h__
|
||||||
#define __iop_cat_h__
|
#define __iop_cat_h__
|
||||||
|
|
||||||
|
#define ACK 0
|
||||||
|
#define CAT_PREFIX 0xC0
|
||||||
|
#define IOP_PREFIX 0xD0
|
||||||
|
#define EEPROM_READ_PREFIX 0xE0
|
||||||
|
#define EEPROM_WRITE_PREFIX 0xF0
|
||||||
|
|
||||||
|
#define IOP_MODE_COMMAND 0x00
|
||||||
|
#define IOP_START_TX_COMMAND 0x01
|
||||||
|
#define IOP_STOP_TX_COMMAND 0x02
|
||||||
|
#define IOP_CW_CONFIG_MSG 0x03
|
||||||
|
|
||||||
|
#define IOP_MODE_REQUEST 0x00
|
||||||
|
#define IOP_CW_STATUS_MSG 0x03
|
||||||
|
|
||||||
|
#define IOP_MODE_SSB 0x00
|
||||||
|
#define IOP_MODE_DIGI 0x01
|
||||||
|
#define IOP_MODE_CW 0x02
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define USBSERIAL Serial
|
#define USBSERIAL Serial
|
||||||
#define HWSERIAL Serial1
|
#define HWSERIAL Serial1
|
||||||
|
|
||||||
|
/*struct IOPTMsg {
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum KeyMode {
|
||||||
|
STRAIGHT = 0,
|
||||||
|
IAMBIC_A,
|
||||||
|
IAMBIC_B,
|
||||||
|
//ULTIMATIC,
|
||||||
|
//BUG,
|
||||||
|
};
|
||||||
|
|
||||||
|
const byte MODE_LETTER[3] = {'S', 'A', 'B'};
|
||||||
|
|
||||||
|
const byte NO_FLAGS = 0;
|
||||||
|
const byte REVERSED = 1;
|
||||||
|
|
||||||
|
#define R_MESSAGE_MAX_LEN 32
|
||||||
|
#define T_MESSAGE_MAX_LEN 32
|
||||||
|
|
||||||
|
struct RMessage {
|
||||||
|
uint8_t id;
|
||||||
|
uint8_t len;
|
||||||
|
byte data[R_MESSAGE_MAX_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TMessage {
|
||||||
|
uint8_t id;
|
||||||
|
uint8_t len;
|
||||||
|
byte data[T_MESSAGE_MAX_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// CW CONFIGURATION MESSAGE
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
struct CWConfig {
|
||||||
|
// mode
|
||||||
|
KeyMode mode = IAMBIC_A;
|
||||||
|
// flags
|
||||||
|
bool reversed = false;
|
||||||
|
// parameters
|
||||||
|
uint8_t wpm = 15;
|
||||||
|
float weight = 3.0;
|
||||||
|
uint16_t sidetone = 700;
|
||||||
|
};
|
||||||
|
|
||||||
|
void packR_CWConfig(RMessage &m, CWConfig const &c)
|
||||||
|
{
|
||||||
|
m.id = IOP_CW_CONFIG_MSG;
|
||||||
|
m.len = 6;
|
||||||
|
// mode
|
||||||
|
m.data[0] = byte(c.mode);
|
||||||
|
// flags
|
||||||
|
m.data[1] = NO_FLAGS;
|
||||||
|
m.data[1] |= (c.reversed ? REVERSED : 0);
|
||||||
|
// parameters
|
||||||
|
m.data[2] = byte(c.wpm);
|
||||||
|
m.data[3] = byte(c.weight * 10.0);
|
||||||
|
m.data[4] = byte(c.sidetone >> 8);
|
||||||
|
m.data[5] = byte(c.sidetone | 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unpackR_CWConfig(CWConfig &c, RMessage const &m)
|
||||||
|
{
|
||||||
|
//if (m.id != IOP_CW_CONFIG_MSG || m.len != 6) {
|
||||||
|
// // do some error thing...
|
||||||
|
//}
|
||||||
|
//mode
|
||||||
|
c.mode = KeyMode(m.data[0]);
|
||||||
|
// flags
|
||||||
|
c.reversed = bool(m.data[1] & REVERSED);
|
||||||
|
// parameters
|
||||||
|
c.wpm = uint8_t(m.data[2]);
|
||||||
|
c.weight = float(m.data[3]) / 10.0;
|
||||||
|
c.sidetone = (m.data[4] << 8) | m.data[5];
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// MODE REQUEST MESSAGE
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
void packT_ModeRequest(TMessage &m)
|
||||||
|
{
|
||||||
|
m.id = IOP_MODE_REQUEST;
|
||||||
|
m.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// CW STATUS MESSAGE
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
//void packT_DisplayText(TMessage &m, CWConfig const &c)
|
||||||
|
//{
|
||||||
|
// m.id = IOP_CW_STATUS_MSG;
|
||||||
|
// m.len = 3;
|
||||||
|
// m.data[0] = ' '; // growth
|
||||||
|
// m.data[1] = MODE_LETTER[c.mode];
|
||||||
|
// m.data[2] = ' '; // TODO: RX filter width
|
||||||
|
//}
|
||||||
|
|
||||||
|
// No unpack required: this is a string to put on the display.
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
void initCAT(long, int);
|
void initCAT(long, int);
|
||||||
void serviceCAT();
|
void serviceCAT();
|
||||||
|
|
||||||
|
|
|
@ -4,18 +4,18 @@
|
||||||
|
|
||||||
#include "cat.h"
|
#include "cat.h"
|
||||||
|
|
||||||
#define ACK 0
|
//#define ACK 0
|
||||||
#define CAT_PREFIX 0xC0
|
//#define CAT_PREFIX 0xC0
|
||||||
#define IOP_PREFIX 0xD0
|
//#define IOP_PREFIX 0xD0
|
||||||
#define EEPROM_READ_PREFIX 0xE0
|
//#define EEPROM_READ_PREFIX 0xE0
|
||||||
#define EEPROM_WRITE_PREFIX 0xF0
|
//#define EEPROM_WRITE_PREFIX 0xF0
|
||||||
|
//
|
||||||
#define IOP_MODE_COMMAND 0x00
|
//#define IOP_MODE_COMMAND 0x00
|
||||||
#define IOP_START_TX_COMMAND 0x01
|
//#define IOP_START_TX_COMMAND 0x01
|
||||||
#define IOP_STOP_TX_COMMAND 0x02
|
//#define IOP_STOP_TX_COMMAND 0x02
|
||||||
#define IOP_MODE_SSB 0x00
|
//#define IOP_MODE_SSB 0x00
|
||||||
#define IOP_MODE_DIGI 0x01
|
//#define IOP_MODE_DIGI 0x01
|
||||||
#define IOP_MODE_CW 0x02
|
//#define IOP_MODE_CW 0x02
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// CAT from PC-to-IOP
|
// CAT from PC-to-IOP
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
#ifndef __iop_config_h__
|
#ifndef __iop_config_h__
|
||||||
#define __iop_config_h__
|
#define __iop_config_h__
|
||||||
|
|
||||||
|
#define KEYER_LEFT_PADDLE_PIN 16
|
||||||
|
#define KEYER_RIGHT_PADDLE_PIN 17
|
||||||
|
|
||||||
// Uncomment to use the "factory" calibration mode. This is intended to
|
// Uncomment to use the "factory" calibration mode. This is intended to
|
||||||
// allow calibration of IOP settings, separately from the uBITX/Raduino.
|
// allow calibration of IOP settings, separately from the uBITX/Raduino.
|
||||||
// There will be no pass-thru of any CAT.
|
// There will be no pass-thru of any CAT.
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
//**********************************************************************
|
||||||
|
//
|
||||||
|
// Keyer, a part of nanoIO
|
||||||
|
//
|
||||||
|
// nanoIO paddle keyer (c) 2018, David Freese, W1HKJ
|
||||||
|
//
|
||||||
|
// based on code from Iambic Keyer Code Keyer Sketch
|
||||||
|
// Copyright (c) 2009 Steven T. Elliott
|
||||||
|
//
|
||||||
|
// nanoIO is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// nanoIO is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
//Revisions:
|
||||||
|
//
|
||||||
|
//1.0.0: Initial release
|
||||||
|
//
|
||||||
|
//**********************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __iop_keyer_h__
|
||||||
|
#define __iop_keyer_h__
|
||||||
|
|
||||||
|
//#include "Arduino.h"
|
||||||
|
|
||||||
|
//#include "config.h"
|
||||||
|
|
||||||
|
#define IAMBICA 0
|
||||||
|
#define IAMBICB 1
|
||||||
|
#define STRAIGHT 2
|
||||||
|
|
||||||
|
class Keyer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
//int cw_pin_;
|
||||||
|
//int ptt_pin_;
|
||||||
|
bool key_down;
|
||||||
|
|
||||||
|
long ktimer;
|
||||||
|
|
||||||
|
int _speed;
|
||||||
|
int _dashlen; // Length of dash
|
||||||
|
int _dotlen; // Length of dot
|
||||||
|
int _space_len; // Length of space
|
||||||
|
float _weight;
|
||||||
|
|
||||||
|
char keyerControl;
|
||||||
|
char keyerState;
|
||||||
|
int key_mode;
|
||||||
|
|
||||||
|
void calc_ratio();
|
||||||
|
void update_PaddleLatch();
|
||||||
|
|
||||||
|
public:
|
||||||
|
Keyer(int wpm, float _weight);
|
||||||
|
//void cw_pin(int pin);
|
||||||
|
//void ptt_pin(int pin);
|
||||||
|
void wpm(int spd);
|
||||||
|
void set_mode(int md);
|
||||||
|
int get_mode() { return key_mode; }
|
||||||
|
bool is_down() { return key_down; }
|
||||||
|
// void set__weight();
|
||||||
|
|
||||||
|
bool do_paddles();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// EOF
|
||||||
|
//======================================================================
|
|
@ -0,0 +1,214 @@
|
||||||
|
//======================================================================
|
||||||
|
//
|
||||||
|
// nanoIO paddle keyer (c) 2018, David Freese, W1HKJ
|
||||||
|
//
|
||||||
|
// based on code from Iambic Keyer Code Keyer Sketch
|
||||||
|
// Copyright (c) 2009 Steven T. Elliott
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details:
|
||||||
|
//
|
||||||
|
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
// Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
//#include "Arduino.h"
|
||||||
|
//#include "TimerOne.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "keyer.h"
|
||||||
|
|
||||||
|
const uint8_t LP_in = KEYER_LEFT_PADDLE_PIN;
|
||||||
|
const uint8_t RP_in = KEYER_RIGHT_PADDLE_PIN;
|
||||||
|
|
||||||
|
//#define ST_Freq 600 // Set the Sidetone Frequency to 600 Hz
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// keyerControl bit definitions
|
||||||
|
//
|
||||||
|
#define DIT_L 0x01 // Dit latch
|
||||||
|
#define DAH_L 0x02 // Dah latch
|
||||||
|
#define DIT_PROC 0x04 // Dit is being processed
|
||||||
|
#define PDLSWAP 0x08 // 0 for normal, 1 for swap
|
||||||
|
//======================================================================
|
||||||
|
//
|
||||||
|
// State Machine Defines
|
||||||
|
|
||||||
|
enum KSTYPE {IDLE, CHK_DIT, CHK_DAH, KEYED_PREP, KEYED, INTER_ELEMENT };
|
||||||
|
|
||||||
|
Keyer::Keyer(int wpm, float weight)
|
||||||
|
{
|
||||||
|
//ptt_pin_ = PTT_PIN;
|
||||||
|
//cw_pin_ = CW_PIN;
|
||||||
|
// Setup outputs
|
||||||
|
pinMode(LP_in, INPUT_PULLUP); // sets Left Paddle digital pin as input
|
||||||
|
pinMode(RP_in, INPUT_PULLUP); // sets Right Paddle digital pin as input
|
||||||
|
|
||||||
|
// pinMode(ST_Pin, OUTPUT); // Sets the Sidetone digital pin as output
|
||||||
|
|
||||||
|
// digitalWrite(LP_in, HIGH); // Enable pullup resistor on Left Paddle Input Pin
|
||||||
|
// digitalWrite(RP_in, HIGH); // Enable pullup resistor on Right Paddle Input Pin
|
||||||
|
|
||||||
|
keyerState = IDLE;
|
||||||
|
keyerControl = 0;
|
||||||
|
key_mode = IAMBICA;
|
||||||
|
key_down = false;
|
||||||
|
_weight = weight;
|
||||||
|
|
||||||
|
_speed = wpm;
|
||||||
|
calc_ratio();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the length of dot, dash and silence
|
||||||
|
void Keyer::calc_ratio()
|
||||||
|
{
|
||||||
|
float w = (1 + _weight) / (_weight -1);
|
||||||
|
_space_len = (1200 / _speed);
|
||||||
|
_dotlen = _space_len * (w - 1);
|
||||||
|
_dashlen = (1 + w) * _space_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
//void Keyer::cw_pin(int pin)
|
||||||
|
//{
|
||||||
|
// ptt_pin_ = pin;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//void Keyer::ptt_pin(int pin)
|
||||||
|
//{
|
||||||
|
// cw_pin_ = pin;
|
||||||
|
//}
|
||||||
|
|
||||||
|
void Keyer::set_mode(int md)
|
||||||
|
{
|
||||||
|
key_mode = md;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyer::wpm(int wpm)
|
||||||
|
{
|
||||||
|
_speed = wpm;
|
||||||
|
calc_ratio();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// Latch paddle press
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
void Keyer::update_PaddleLatch()
|
||||||
|
{
|
||||||
|
if (digitalRead(LP_in) == LOW) {
|
||||||
|
keyerControl |= DIT_L;
|
||||||
|
}
|
||||||
|
if (digitalRead(RP_in) == LOW) {
|
||||||
|
keyerControl |= DAH_L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Keyer::do_paddles()
|
||||||
|
{
|
||||||
|
if (key_mode == STRAIGHT) { // Straight Key
|
||||||
|
if ((digitalRead(LP_in) == LOW) || (digitalRead(RP_in) == LOW)) {
|
||||||
|
// Key from either paddle
|
||||||
|
// digitalWrite(ptt_pin_, HIGH);
|
||||||
|
// digitalWrite(cw_pin_, HIGH);
|
||||||
|
// tone(ST_Pin, 600);
|
||||||
|
key_down = true;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// digitalWrite(ptt_pin_, LOW);
|
||||||
|
// digitalWrite(cw_pin_, LOW);
|
||||||
|
// noTone(ST_Pin);
|
||||||
|
key_down = false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// keyerControl contains processing flags and keyer mode bits
|
||||||
|
// Supports Iambic A and B
|
||||||
|
// State machine based, uses calls to millis() for timing.
|
||||||
|
switch (keyerState) {
|
||||||
|
case IDLE: // Wait for direct or latched paddle press
|
||||||
|
if ((digitalRead(LP_in) == LOW) || (digitalRead(RP_in) == LOW) || (keyerControl & 0x03)) {
|
||||||
|
update_PaddleLatch();
|
||||||
|
keyerState = CHK_DIT;
|
||||||
|
// letting this fall through // return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// break;
|
||||||
|
case CHK_DIT: // See if the dit paddle was pressed
|
||||||
|
if (keyerControl & DIT_L) {
|
||||||
|
keyerControl |= DIT_PROC;
|
||||||
|
ktimer = _dotlen;
|
||||||
|
keyerState = KEYED_PREP;
|
||||||
|
return true;
|
||||||
|
} else { // fall through
|
||||||
|
keyerState = CHK_DAH;
|
||||||
|
}
|
||||||
|
case CHK_DAH: // See if dah paddle was pressed
|
||||||
|
if (keyerControl & DAH_L) {
|
||||||
|
ktimer = _dashlen;
|
||||||
|
keyerState = KEYED_PREP;
|
||||||
|
// letting this fall through // return true;
|
||||||
|
} else {
|
||||||
|
keyerState = IDLE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// break;
|
||||||
|
case KEYED_PREP: // Assert key down, start timing
|
||||||
|
// state shared for dit or dah
|
||||||
|
// digitalWrite(ptt_pin_, HIGH); // Enable PTT
|
||||||
|
// tone(ST_Pin, ST_Freq); // Turn the Sidetone on
|
||||||
|
// digitalWrite(cw_pin_, HIGH); // Key the CW line
|
||||||
|
key_down = true;
|
||||||
|
ktimer += millis(); // set ktimer to interval end time
|
||||||
|
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
||||||
|
keyerState = KEYED; // next state
|
||||||
|
// letting this fall through // return true;
|
||||||
|
// break;
|
||||||
|
case KEYED: // Wait for timer to expire
|
||||||
|
if (millis() > ktimer) { // are we at end of key down ?
|
||||||
|
// digitalWrite(ptt_pin_, LOW); // Disable PTT
|
||||||
|
// noTone(ST_Pin); // Turn the Sidetone off
|
||||||
|
// digitalWrite(cw_pin_, LOW); // Unkey the CW line
|
||||||
|
key_down = false;
|
||||||
|
ktimer = millis() + _space_len; // inter-element time
|
||||||
|
keyerState = INTER_ELEMENT; // next state
|
||||||
|
// letting this fall through // return true;
|
||||||
|
} else if (key_mode == IAMBICB) { // Iambic B Mode ?
|
||||||
|
update_PaddleLatch(); // yes, early paddle latch in Iambic B mode
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// break;
|
||||||
|
|
||||||
|
case INTER_ELEMENT: // Insert time between dits/dahs
|
||||||
|
update_PaddleLatch(); // latch paddle state
|
||||||
|
if (millis() > ktimer) { // are we at end of inter-space ?
|
||||||
|
if (keyerControl & DIT_PROC) { // was it a dit or dah ?
|
||||||
|
keyerControl &= ~(DIT_L + DIT_PROC); // clear two bits
|
||||||
|
keyerState = CHK_DAH; // dit done, check for dah
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
keyerControl &= ~(DAH_L); // clear dah latch
|
||||||
|
keyerState = IDLE; // go idle
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // resolve compiler warning; do we ever get here?
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// EOF
|
||||||
|
//======================================================================
|
|
@ -0,0 +1,52 @@
|
||||||
|
//======================================================================
|
||||||
|
// menu.h
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
#ifndef __menu_h__
|
||||||
|
#define __menu_h__
|
||||||
|
|
||||||
|
// 16 characters on display
|
||||||
|
#define MAX_TEXT_LEN 16
|
||||||
|
#define MENU_SELECTED_CHAR '>'
|
||||||
|
/*
|
||||||
|
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:
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// EOF
|
||||||
|
//======================================================================
|
|
@ -0,0 +1,139 @@
|
||||||
|
//======================================================================
|
||||||
|
// menu.ino
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
#include "menu.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
CW mode:
|
||||||
|
WPM (although we can get this from Raduino)
|
||||||
|
WPM: # (L/R, select/abort)
|
||||||
|
FILT
|
||||||
|
WIDE NORM NARR
|
||||||
|
|
||||||
|
SSB mode:
|
||||||
|
TX LVL
|
||||||
|
COMP
|
||||||
|
FILT
|
||||||
|
WIDE NORM NARR
|
||||||
|
|
||||||
|
Digi mode:
|
||||||
|
TX LVL
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MenuItem {
|
||||||
|
public:
|
||||||
|
MenuItem() {}
|
||||||
|
virtual MenuItem* next() = 0;
|
||||||
|
virtual MenuItem* prev() = 0;
|
||||||
|
char text[MAX_TEXT_LEN + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextMenu : public MenuItem {
|
||||||
|
public:
|
||||||
|
TextMenu(int num_entries, int entry_len): MenuItem(), _num_entries(num_entries), _entry_len(entry_len), _selected(0), _leftmost(0) {
|
||||||
|
text[0] = '\0';
|
||||||
|
_entries = new MenuItem*[_num_entries];
|
||||||
|
_labels = new char*[_num_entries];
|
||||||
|
for (int i = 0; i < _num_entries; i++) {
|
||||||
|
_labels[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~TextMenu() {
|
||||||
|
for (int i = 0; i < _num_entries; i++) {
|
||||||
|
if (_labels[i] != NULL) {
|
||||||
|
delete _labels[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete _labels;
|
||||||
|
delete _entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual MenuItem* next() {
|
||||||
|
bool dirty = false;
|
||||||
|
|
||||||
|
if (++_selected == _num_entries) {
|
||||||
|
_selected = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_selected < _leftmost) {
|
||||||
|
_leftmost = _selected;
|
||||||
|
dirty = true;
|
||||||
|
} else {
|
||||||
|
while ((_selected - _leftmost) * _entry_len >= MAX_TEXT_LEN) {
|
||||||
|
_leftmost++;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirty) {
|
||||||
|
for (int i = _leftmost; i < _num_entries; i++) {
|
||||||
|
strncpy(&text[i - _leftmost], _labels[i], _entry_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text[_selected - _leftmost] = MENU_SELECTED_CHAR;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual MenuItem* prev() {
|
||||||
|
bool dirty = false;
|
||||||
|
|
||||||
|
if (_selected-- == 0) {
|
||||||
|
_selected += _num_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_selected < _leftmost) {
|
||||||
|
_leftmost = _selected;
|
||||||
|
dirty = true;
|
||||||
|
} else {
|
||||||
|
while ((_selected - _leftmost) * _entry_len >= MAX_TEXT_LEN) {
|
||||||
|
_leftmost++;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirty) {
|
||||||
|
updateText();
|
||||||
|
} else {
|
||||||
|
updateCursor();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addEntry(int i, const char* label, MenuItem* entry) {
|
||||||
|
if (i < _num_entries) {
|
||||||
|
_labels[i] = new char[strlen(label) + 1]; // I need to learn to do strings the C++ way.
|
||||||
|
strcpy(_labels[i], label); // Ditto.
|
||||||
|
_entries[i] = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateText() {
|
||||||
|
for (int i = _leftmost; i < _num_entries; i++) {
|
||||||
|
strncpy(&text[i - _leftmost], _labels[i], _entry_len);
|
||||||
|
}
|
||||||
|
text[_selected - _leftmost] = MENU_SELECTED_CHAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateCursor() {
|
||||||
|
text[_selected - _leftmost] = MENU_SELECTED_CHAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*MenuItem* operator[](int i) {
|
||||||
|
return this->entries[i];
|
||||||
|
}*/
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _num_entries;
|
||||||
|
int _entry_len;
|
||||||
|
int _selected;
|
||||||
|
int _leftmost;
|
||||||
|
char** _labels;
|
||||||
|
MenuItem** _entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// EOF
|
||||||
|
//======================================================================
|
|
@ -9,6 +9,7 @@
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "cat.h"
|
#include "cat.h"
|
||||||
#include "eeprom.h"
|
#include "eeprom.h"
|
||||||
|
#include "keyer.h"
|
||||||
|
|
||||||
// comment this out to disable debugging code
|
// comment this out to disable debugging code
|
||||||
//#define DEBUG
|
//#define DEBUG
|
||||||
|
@ -29,6 +30,8 @@ enum TxState {
|
||||||
|
|
||||||
extern RigMode rigMode;
|
extern RigMode rigMode;
|
||||||
|
|
||||||
|
extern bool keyerKeyDown;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
|
@ -19,6 +19,13 @@ Bounce linePTT = Bounce();
|
||||||
|
|
||||||
TxState txState = TX_OFF;
|
TxState txState = TX_OFF;
|
||||||
|
|
||||||
|
Keyer keyer(15, 3.0); // need to make configurable
|
||||||
|
|
||||||
|
//SSBMenu ssbMenu();
|
||||||
|
//DigiMenu digiMenu();
|
||||||
|
//CWMenu cwMenu();
|
||||||
|
//MenuItem* dspMenu = &ssbMenu;
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// catPTTOn()
|
// catPTTOn()
|
||||||
//
|
//
|
||||||
|
@ -195,6 +202,7 @@ void setRigMode(RigMode m)
|
||||||
// automatically overridden by mic-in, if the mic PTT is pressed.
|
// automatically overridden by mic-in, if the mic PTT is pressed.
|
||||||
audioSelectTxInput(TX_LINE_IN);
|
audioSelectTxInput(TX_LINE_IN);
|
||||||
audioSSBFilter();
|
audioSSBFilter();
|
||||||
|
// dspMenu = &ssbMenu;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MODE_DIGI:
|
case MODE_DIGI:
|
||||||
|
@ -207,12 +215,14 @@ void setRigMode(RigMode m)
|
||||||
// than using CAT for PTT control.
|
// than using CAT for PTT control.
|
||||||
audioSelectTxInput(TX_USB_IN);
|
audioSelectTxInput(TX_USB_IN);
|
||||||
audioDigiFilter();
|
audioDigiFilter();
|
||||||
|
// dspMenu = &digiMenu;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MODE_CW:
|
case MODE_CW:
|
||||||
// CW just gets the radio off of Mic-In; but it won't use Line-In.
|
// CW just gets the radio off of Mic-In; but it won't use Line-In.
|
||||||
audioSelectTxInput(TX_LINE_IN);
|
audioSelectTxInput(TX_LINE_IN);
|
||||||
audioCWFilter();
|
audioCWFilter();
|
||||||
|
// dspMenu = &cwMenu;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,12 +249,32 @@ void setup() {
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
elapsedMillis frame_timer = 0;
|
elapsedMillis elapsed = 0;
|
||||||
|
|
||||||
|
switch(rigMode) {
|
||||||
|
case MODE_CW:
|
||||||
|
if (keyer.do_paddles()) {
|
||||||
|
if (keyer.is_down()) {
|
||||||
|
digitalWrite(PTT_KEY_OUT_PIN, LOW);
|
||||||
|
} else {
|
||||||
|
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
|
||||||
|
}
|
||||||
|
// No break... if the paddle is not active, I want this to fall
|
||||||
|
// through to checkMicPTT etc... but return early if the paddle is
|
||||||
|
// active, to maximize responsiveness. Probably could just use
|
||||||
|
// 'if' statements here instead of the 'switch'.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
checkMicPTT();
|
||||||
|
checkLinePTT();
|
||||||
|
serviceCAT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//dspMenu->update();
|
||||||
|
|
||||||
checkMicPTT();
|
|
||||||
checkLinePTT();
|
|
||||||
serviceCAT();
|
|
||||||
/*
|
/*
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
int frame_skews = 0; // for debugging; see how often we skew frames
|
int frame_skews = 0; // for debugging; see how often we skew frames
|
||||||
|
|
Loading…
Reference in New Issue