Merge pull request #12 from reedbn/morse-menu

More work is probably needed here, but this is working better than nothing.
This commit is contained in:
reedbn 2020-02-04 21:50:16 -08:00 committed by GitHub
commit 94aae2f289
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 323 additions and 152 deletions

101
morse.cpp
View File

@ -15,48 +15,53 @@ struct Morse {
* The first zero after the 1s indicates the start of the letter, it MUST be discarded
*/
static const PROGMEM struct Morse morse_table[] = {
{'a', 0xf9}, // 11111001
{'b', 0xe8}, // 11101000
{'c', 0xea}, // 11101010
{'d', 0xf4}, // 11110100
{'e', 0xfc}, // 11111100
{'f', 0xe2}, // 11100010
{'g', 0xf6}, // 11110110
{'h', 0xe0}, // 11100000
{'i', 0xf8}, // 11111000
{'j', 0xe7}, // 11100111
{'k', 0xf6}, // 11110101
{'l', 0xe4}, // 11100100
{'m', 0xfb}, // 11111011
{'n', 0xfa}, // 11111010
{'o', 0xf7}, // 11110111
{'p', 0xe6}, // 11100110
{'q', 0xed}, // 11101101
{'r', 0xf2}, // 11110010
{'s', 0xf0}, // 11110000
{'t', 0xfd}, // 11111101
{'u', 0xf1}, // 11110001
{'v', 0xe1}, // 11100001
{'w', 0xf3}, // 11110011
{'x', 0xe9}, // 11101001
{'y', 0xe3}, // 11101011
{'z', 0xec}, // 11101100
{'1', 0xcf}, // 11001111
{'2', 0xc7}, // 11000111
{'3', 0xc3}, // 11000011
{'4', 0xc1}, // 11000001
{'5', 0xc0}, // 11000000
{'6', 0xd0}, // 11010000
{'7', 0xd8}, // 11011000
{'8', 0xdc}, // 11011100
{'9', 0xde}, // 11011110
{'0', 0xdf}, // 11011111
{'.', 0x95}, // 10010101
{',', 0xb3}, // 10110011
{'?', 0x8c}, // 10001100
{'a', 0b11111001},
{'b', 0b11101000},
{'c', 0b11101010},
{'d', 0b11110100},
{'e', 0b11111100},
{'f', 0b11100010},
{'g', 0b11110110},
{'h', 0b11100000},
{'i', 0b11111000},
{'j', 0b11100111},
{'k', 0b11110101},
{'l', 0b11100100},
{'m', 0b11111011},
{'n', 0b11111010},
{'o', 0b11110111},
{'p', 0b11100110},
{'q', 0b11101101},
{'r', 0b11110010},
{'s', 0b11110000},
{'t', 0b11111101},
{'u', 0b11110001},
{'v', 0b11100001},
{'w', 0b11110011},
{'x', 0b11101001},
{'y', 0b11101011},
{'z', 0b11101100},
{'1', 0b11001111},
{'2', 0b11000111},
{'3', 0b11000011},
{'4', 0b11000001},
{'5', 0b11000000},
{'6', 0b11010000},
{'7', 0b11011000},
{'8', 0b11011100},
{'9', 0b11011110},
{'0', 0b11011111},
{'.', 0b10010101},
{',', 0b10110011},
{'?', 0b10001100},
{ 2 , 0b11010101}, // ASCII 0x02 is Start of Text - <CT>
{ 4 , 0b10000101}, // ASCII 0x04 is End of Transmission - <CL> is too long for our encoding scheme in 8 bits, but <SK> fits
};
static void morseLetter(char c, uint16_t dit_duration_ms){
void morseLetter(char c, uint16_t dit_duration_ms){
if(!globalSettings.morseMenuOn){
return;
}
unsigned char mask = 0x80;
//handle space character as three dashes
@ -100,9 +105,23 @@ static void morseLetter(char c, uint16_t dit_duration_ms){
}
}
static const uint8_t RELATIVE_OFFSET_HZ = 100;
void morseText(char *text, uint16_t dit_duration_ms){
while(*text){
int16_t total_counts = 0;
morseBool(false);
enc_read();//Don't count initial tone against total_counts
while(*text && (abs(total_counts) < 10)){
morseLetter(*text++, dit_duration_ms);
total_counts += enc_read();
}
}
void morseBool(bool val){
if(!globalSettings.morseMenuOn){
return;
}
tone(CW_TONE, globalSettings.cwSideToneFreq + (val ? RELATIVE_OFFSET_HZ : -RELATIVE_OFFSET_HZ));
delay(3*globalSettings.cwDitDurationMs);
noTone(CW_TONE);
delay(3*globalSettings.cwDitDurationMs);
}

View File

@ -1,3 +1,7 @@
#include "settings.h"
//sends out morse code at the speed set by cwSpeed
void morseLetter(char c, uint16_t dit_duration_ms = globalSettings.cwDitDurationMs);
void morseText(char *text, uint16_t dit_duration_ms = globalSettings.cwDitDurationMs);
//Plays either a higher or lower tone to indicate a boolean value
void morseBool(bool val);

View File

@ -20,10 +20,11 @@ static const uint16_t EEPROM_ADDR_TOUCH_SLOPE_X = 32;//int16_t
static const uint16_t EEPROM_ADDR_TOUCH_SLOPE_Y = 36;//int16_t
static const uint16_t EEPROM_ADDR_TOUCH_OFFSET_X = 40;//int16_t
static const uint16_t EEPROM_ADDR_TOUCH_OFFSET_Y = 44;//int16_t
static const uint16_t EEPROM_ADDR_CW_DELAYTIME = 48;
static const uint16_t EEPROM_ADDR_VFO_A_MODE = 256;
static const uint16_t EEPROM_ADDR_VFO_B_MODE = 257;
static const uint16_t EEPROM_ADDR_CW_KEY_TYPE = 358;
static const uint16_t EEPROM_ADDR_MORSE_MENU = 46;//uint8_t
static const uint16_t EEPROM_ADDR_CW_DELAYTIME = 48;//uint16_t
static const uint16_t EEPROM_ADDR_VFO_A_MODE = 256;//uint8_t
static const uint16_t EEPROM_ADDR_VFO_B_MODE = 257;//uint8_t
static const uint16_t EEPROM_ADDR_CW_KEY_TYPE = 358;//uint8_t
template<typename T>
bool LoadSane(T& dest,uint16_t addr, T min, T max)
@ -81,6 +82,7 @@ void LoadDefaultSettings()
globalSettings.txActive = false;
globalSettings.txCatActive = false;
globalSettings.cwExpirationTimeMs = 0;
globalSettings.morseMenuOn = false;
}
void LoadSettingsFromEeprom()
@ -97,6 +99,10 @@ void LoadSettingsFromEeprom()
LoadSane(globalSettings.vfoB.mode,EEPROM_ADDR_VFO_B_MODE,VFO_MODE_LSB,VFO_MODE_USB);
LoadSane(globalSettings.keyerMode,EEPROM_ADDR_CW_KEY_TYPE,KEYER_STRAIGHT,KEYER_IAMBIC_B);
uint8_t morse_on = 0;
LoadSane(morse_on,EEPROM_ADDR_MORSE_MENU,(uint8_t)0,(uint8_t)1);
globalSettings.morseMenuOn = morse_on;
//No sanity check on these - cal your heart out
EEPROM.get(EEPROM_ADDR_MASTER_CAL,globalSettings.oscillatorCal);
EEPROM.get(EEPROM_ADDR_TOUCH_SLOPE_X,globalSettings.touchSlopeX);
@ -122,6 +128,7 @@ void SaveSettingsToEeprom()
EEPROM.put(EEPROM_ADDR_VFO_A_MODE,globalSettings.vfoA.mode);
EEPROM.put(EEPROM_ADDR_VFO_B_MODE,globalSettings.vfoB.mode);
EEPROM.put(EEPROM_ADDR_CW_KEY_TYPE,globalSettings.keyerMode);
EEPROM.put(EEPROM_ADDR_MORSE_MENU,(uint8_t)globalSettings.morseMenuOn);
}
uint32_t GetActiveVfoFreq()

View File

@ -97,6 +97,7 @@ struct SettingsRam
bool txActive;
bool txCatActive;
uint32_t cwExpirationTimeMs;
bool morseMenuOn;
};
//This is the shared declaration

159
setup.cpp
View File

@ -226,38 +226,6 @@ const SettingScreen_t ssBfo PROGMEM = {
};
void runBfoSetting(){runSetting(&ssBfo);}
//CW Speed
void ssCwSpeedInitialize(long int* start_value_out)
{
*start_value_out = 1200L/globalSettings.cwDitDurationMs;
}
void ssCwSpeedValidate(const long int candidate_value_in, long int* validated_value_out)
{
*validated_value_out = LIMIT(candidate_value_in,1,100);
}
void ssCwSpeedChange(const long int new_value, char* buff_out, const size_t /*buff_out_size*/)
{
ltoa(new_value, buff_out, 10);
}
void ssCwSpeedFinalize(const long int final_value)
{
globalSettings.cwDitDurationMs = 1200L/final_value;
SaveSettingsToEeprom();
}
const char SS_CW_SPEED_T [] PROGMEM = "CW Play Speed";
const char SS_CW_SPEED_A [] PROGMEM = "Select speed to play CW\ncharacters";
const SettingScreen_t ssCwSpeed PROGMEM = {
SS_CW_SPEED_T,
SS_CW_SPEED_A,
5,
1,
ssCwSpeedInitialize,
ssCwSpeedValidate,
ssCwSpeedChange,
ssCwSpeedFinalize
};
void runCwSpeedSetting(){runSetting(&ssCwSpeed);}
//CW Tone
void ssCwToneInitialize(long int* start_value_out)
{
@ -280,7 +248,7 @@ void ssCwToneFinalize(const long int final_value)
globalSettings.cwSideToneFreq = final_value;
SaveSettingsToEeprom();
}
const char SS_CW_TONE_T [] PROGMEM = "CW Tone Frequency";
const char SS_CW_TONE_T [] PROGMEM = "Tone";
const char SS_CW_TONE_A [] PROGMEM = "Select a frequency that\nCW mode to tune for";
const SettingScreen_t ssTone PROGMEM = {
SS_CW_TONE_T,
@ -307,13 +275,15 @@ void ssCwSwitchDelayChange(const long int new_value, char* buff_out, const size_
{
ltoa(new_value,buff_out,10);
strncat_P(buff_out,(const char*)F("ms"),buff_out_size - strlen(buff_out));
morseText(buff_out);
enc_read();//Consume any rotations during morse playback
}
void ssCwSwitchDelayFinalize(const long int final_value)
{
globalSettings.cwActiveTimeoutMs = final_value;
SaveSettingsToEeprom();
}
const char SS_CW_SWITCH_T [] PROGMEM = "CW Tx -> Rx Switch Delay";
const char SS_CW_SWITCH_T [] PROGMEM = "Tx to Rx Delay";
const char SS_CW_SWITCH_A [] PROGMEM = "Select how long the radio\nshould wait before switching\nbetween TX and RX when in\nCW mode";
const SettingScreen_t ssCwSwitchDelay PROGMEM = {
SS_CW_SWITCH_T,
@ -338,22 +308,28 @@ void ssKeyerValidate(const long int candidate_value_in, long int* validated_valu
}
void ssKeyerChange(const long int new_value, char* buff_out, const size_t buff_out_size)
{
char m;
if(KeyerMode_e::KEYER_STRAIGHT == new_value){
strncpy_P(buff_out,(const char*)F("< Hand Key >"),buff_out_size);
strncpy_P(buff_out,(const char*)F("Hand Key"),buff_out_size);
m = 'S';
}
else if(KeyerMode_e::KEYER_IAMBIC_A == new_value){
strncpy_P(buff_out,(const char*)F("< Iambic A >"),buff_out_size);
strncpy_P(buff_out,(const char*)F("Iambic A"),buff_out_size);
m = 'A';
}
else{
strncpy_P(buff_out,(const char*)F("< Iambic B >"),buff_out_size);
strncpy_P(buff_out,(const char*)F("Iambic B"),buff_out_size);
m = 'B';
}
morseLetter(m);
enc_read();//Consume any rotations during morse playback
}
void ssKeyerFinalize(const long int final_value)
{
globalSettings.keyerMode = (KeyerMode_e)final_value;
SaveSettingsToEeprom();
}
const char SS_KEYER_T [] PROGMEM = "CW Keyer/Paddle Type";
const char SS_KEYER_T [] PROGMEM = "Keyer Type";
const char SS_KEYER_A [] PROGMEM = "Select which type of\nkeyer/paddle is being used";
const SettingScreen_t ssKeyer PROGMEM = {
SS_KEYER_T,
@ -367,6 +343,82 @@ const SettingScreen_t ssKeyer PROGMEM = {
};
void runKeyerSetting(){runSetting(&ssKeyer);}
//Morse menu playback
void ssMorseMenuInitialize(long int* start_value_out)
{
*start_value_out = globalSettings.morseMenuOn;
}
void ssMorseMenuValidate(const long int candidate_value_in, long int* validated_value_out)
{
*validated_value_out = LIMIT(candidate_value_in,0,1);
}
void ssMorseMenuChange(const long int new_value, char* buff_out, const size_t buff_out_size)
{
char m;
if(new_value){
strncpy_P(buff_out,(const char*)F("Yes"),buff_out_size);
m = 'Y';
}
else{
strncpy_P(buff_out,(const char*)F("No"),buff_out_size);
m = 'N';
}
morseLetter(m);
enc_read();//Consume any rotations during morse playback
}
void ssMorseMenuFinalize(const long int final_value)
{
globalSettings.morseMenuOn = final_value;
SaveSettingsToEeprom();
}
const char SS_MORSE_MENU_T [] PROGMEM = "Menu Audio";
const char SS_MORSE_MENU_A [] PROGMEM = "When on, menu selections\nwill play morse code";
const SettingScreen_t ssMorseMenu PROGMEM = {
SS_MORSE_MENU_T,
SS_MORSE_MENU_A,
10,
1,
ssMorseMenuInitialize,
ssMorseMenuValidate,
ssMorseMenuChange,
ssMorseMenuFinalize
};
void runMorseMenuSetting(){runSetting(&ssMorseMenu);}
//CW Speed
void ssCwSpeedInitialize(long int* start_value_out)
{
*start_value_out = 1200L/globalSettings.cwDitDurationMs;
}
void ssCwSpeedValidate(const long int candidate_value_in, long int* validated_value_out)
{
*validated_value_out = LIMIT(candidate_value_in,1,100);
}
void ssCwSpeedChange(const long int new_value, char* buff_out, const size_t /*buff_out_size*/)
{
ltoa(new_value, buff_out, 10);
morseText(buff_out,1200L/new_value);
enc_read();//Consume any rotations during morse playback
}
void ssCwSpeedFinalize(const long int final_value)
{
globalSettings.cwDitDurationMs = 1200L/final_value;
SaveSettingsToEeprom();
}
const char SS_CW_SPEED_T [] PROGMEM = "Play Speed";
const char SS_CW_SPEED_A [] PROGMEM = "Select speed to play CW\ncharacters";
const SettingScreen_t ssCwSpeed PROGMEM = {
SS_CW_SPEED_T,
SS_CW_SPEED_A,
5,
1,
ssCwSpeedInitialize,
ssCwSpeedValidate,
ssCwSpeedChange,
ssCwSpeedFinalize
};
void runCwSpeedSetting(){runSetting(&ssCwSpeed);}
//Reset all settings
void ssResetAllInitialize(long int* start_value_out)
{
@ -378,12 +430,17 @@ void ssResetAllValidate(const long int candidate_value_in, long int* validated_v
}
void ssResetAllChange(const long int new_value, char* buff_out, const size_t buff_out_size)
{
char m;
if(new_value){
strncpy_P(buff_out,(const char*)F("Yes"),buff_out_size);
m = 'Y';
}
else{
strncpy_P(buff_out,(const char*)F("No"),buff_out_size);
m = 'N';
}
morseLetter(m);
enc_read();//Consume any rotations during morse playback
}
void ssResetAllFinalize(const long int final_value)
{
@ -393,7 +450,7 @@ void ssResetAllFinalize(const long int final_value)
setup();
}
}
const char SS_RESET_ALL_T [] PROGMEM = "Reset All Cals/Settings";
const char SS_RESET_ALL_T [] PROGMEM = "Reset All";
const char SS_RESET_ALL_A [] PROGMEM = "WARNING: Selecting \"Yes\"\nwill reset all calibrations and\nsettings to their default\nvalues";
const SettingScreen_t ssResetAll PROGMEM = {
SS_RESET_ALL_T,
@ -425,13 +482,14 @@ const MenuItem_t calibrationMenu [] PROGMEM {
};
void runCalibrationMenu(){RUN_MENU(calibrationMenu);}
const char MT_CW [] PROGMEM = "CW/Morse Setup";
const char MT_CW [] PROGMEM = "CW Setup";
const MenuItem_t cwMenu [] PROGMEM {
{MT_CW,nullptr},//Title
{SS_CW_SPEED_T,runCwSpeedSetting},
{SS_CW_TONE_T,runToneSetting},
{SS_CW_SWITCH_T,runCwSwitchDelaySetting},
{SS_KEYER_T,runKeyerSetting},
{SS_MORSE_MENU_T,runMorseMenuSetting},
{SS_CW_SPEED_T,runCwSpeedSetting},
};
void runCwMenu(){RUN_MENU(cwMenu);}
@ -482,10 +540,10 @@ void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items)
static const unsigned int COUNTS_PER_ITEM = 10;
const int MAX_KNOB_VALUE = num_items*COUNTS_PER_ITEM - 1;
int knob_sum = 0;
unsigned int old_index = 0;
unsigned int old_index = -1;
drawMenu(menu_items,num_items);
movePuck(1,0);//Force draw of puck
movePuck(-1,0);//Force draw of puck
//wait for the button to be raised up
while(btnDown()){
@ -504,6 +562,21 @@ void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items)
uint16_t index = knob_sum/COUNTS_PER_ITEM;
movePuck(old_index,index);
if(globalSettings.morseMenuOn //Only spend cycles copying menu item into RAM if we actually need to
&& (old_index != index)){
if(num_items-1 > index){
MenuItem_t mi = {"",nullptr};
memcpy_P(&mi,&menu_items[index+1],sizeof(mi));//The 0th element in the array is the title, so offset by 1
strncpy_P(b,mi.ItemName,sizeof(b));
}
else{
strncpy_P(b,MI_EXIT,sizeof(b));
}
morseText(b);
enc_read();//Consume any rotations during morse playback
}
old_index = index;
if (!btnDown()){

View File

@ -84,29 +84,55 @@ struct Button {
unsigned int id;
char text[5];
char morse;
void (*morse_status)(int8_t* val_out);//-1 if a low tone should play, +1 if a high tone should play
};
void msVfoA(int8_t* val_out){
*val_out = (Vfo_e::VFO_A == globalSettings.activeVfo) ? 1 : -1;
}
void msVfoB(int8_t* val_out){
*val_out = (Vfo_e::VFO_B == globalSettings.activeVfo) ? 1 : -1;
}
void msRit(int8_t* val_out){
*val_out = globalSettings.ritOn ? 1 : -1;
}
void msUsb(int8_t* val_out){
*val_out = (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) ? 1 : -1;
}
void msLsb(int8_t* val_out){
*val_out = (VfoMode_e::VFO_MODE_LSB == GetActiveVfoMode()) ? 1 : -1;
}
void msCw(int8_t* val_out){
*val_out = (TuningMode_e::TUNE_CW == globalSettings.tuningMode) ? 1 : -1;
}
void msSpl(int8_t* val_out){
*val_out = globalSettings.splitOn ? 1 : -1;
}
void msIgnore(int8_t* val_out){
*val_out = 0;
}
constexpr Button btn_set[BUTTON_TOTAL] PROGMEM = {
{LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOA, "VFOA", 'A'},
{LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOB, "VFOB", 'B'},
{LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOA, "VFOA", 'A', msVfoA},
{LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOB, "VFOB", 'B', msVfoB},
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_RIT, "RIT", 'R'},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_USB, "USB", 'U'},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_LSB, "LSB", 'L'},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_CW , "CW", 'C'},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_SPL, "SPL", 'S'},
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_RIT, "RIT", 'R', msRit},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_USB, "USB", 'U', msUsb},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_LSB, "LSB", 'L', msLsb},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_CW , "CW", 'C', msCw},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_SPL, "SPL", 'S', msSpl},
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_80, "80", '8'},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_40, "40", '4'},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_30, "30", '3'},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_20, "20", '2'},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_17, "17", '7'},
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_80, "80", '8', msIgnore},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_40, "40", '4', msIgnore},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_30, "30", '3', msIgnore},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_20, "20", '2', msIgnore},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_17, "17", '7', msIgnore},
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_15 , "15", '5'},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_10 , "10", '1'},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_BLANK_1, "", '\0'},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "\x7F", 'M'},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F'},
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_15 , "15", '5', msIgnore},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_10 , "10", '1', msIgnore},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_BLANK_1, "", '\0', msIgnore},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "\x7F", 'M', msIgnore},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F', msIgnore},
};
static const unsigned int KEYS_OFFSET = 256;//Unique from buttons
@ -129,23 +155,23 @@ enum keypad_e {
KEYS_TOTAL = KEYS_CANCEL - KEYS_OFFSET + 1
};
constexpr Button keypad[KEYS_TOTAL] PROGMEM = {
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_1, "1", '1'},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_2, "2", '2'},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_3, "3", '3'},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BLANK_1, "", '\0'},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_OK, "OK", 'K'},
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_1, "1", '1', msIgnore},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_2, "2", '2', msIgnore},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_3, "3", '3', msIgnore},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BLANK_1, "", '\0', msIgnore},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_OK, "OK", 'K', msIgnore},
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_4, "4", '4'},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_5, "5", '5'},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_6, "6", '6'},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_0, "0", '0'},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BACKSPACE, "<-", 'B'},
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_4, "4", '4', msIgnore},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_5, "5", '5', msIgnore},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_6, "6", '6', msIgnore},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_0, "0", '0', msIgnore},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BACKSPACE, "<-", 'B', msIgnore},
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_7, "7", '7'},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_8, "8", '8'},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_9, "9", '9'},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BLANK_2, "", '\0'},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_CANCEL, "Can", 'C'},
{LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_7, "7", '7', msIgnore},
{LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_8, "8", '8', msIgnore},
{LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_9, "9", '9', msIgnore},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BLANK_2, "", '\0', msIgnore},
{LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_CANCEL, "Can", 'C', msIgnore},
};
boolean getButton(btn_set_e index, Button* button){
@ -357,7 +383,7 @@ void fastTune(){
//if the btn is down, wait until it is up
while(btnDown())
active_delay(50);
active_delay(300);
active_delay(50);
strncpy_P(c,(const char*)F("Fast tune"),sizeof(c));
displayText(c, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
@ -371,7 +397,7 @@ void fastTune(){
//wait until the button is realsed and then return
while(btnDown())
active_delay(50);
active_delay(300);
active_delay(50);
return;
}
@ -400,12 +426,23 @@ void enterFreq(){
btnDraw(&button);
}
while(btnDown())
active_delay(50);
active_delay(50);
int cursor_pos = 0;
memset(c, 0, sizeof(c));
while(1){
bool exit = false;
while(!exit){
checkCAT();
if(btnDown()){
while(btnDown())
active_delay(50);
active_delay(50);
break;
}
if(!readTouch())
continue;
@ -450,8 +487,7 @@ void enterFreq(){
setFrequency(new_freq);
saveVFOs();
}
guiUpdate();
return;
exit = true;
break;
}
@ -466,8 +502,7 @@ void enterFreq(){
}
case KEYS_CANCEL:
{
guiUpdate();
return;
exit = true;
break;
}
case KEYS_0:
@ -500,7 +535,10 @@ void enterFreq(){
active_delay(300);
while(readTouch())
checkCAT();
} // end of event loop : while(1)
} // end of event loop : while(!exit)
guiUpdate();
enc_read();//clear out any tuner turning that happened during entry
}
void drawCWStatus(){
@ -730,22 +768,18 @@ void doCommand(Button* button){
}
case BUTTON_VFOA:
{
if(VFO_A == globalSettings.activeVfo){
fastTune();
}
else{
switchVFO(VFO_A);
}
switchVFO(VFO_A);
uint32_t freq = globalSettings.vfoA.frequency;
ltoa(freq,b,10);
morseText(b);
break;
}
case BUTTON_VFOB:
{
if(VFO_B == globalSettings.activeVfo){
fastTune();
}
else{
switchVFO(VFO_B);
}
switchVFO(VFO_B);
uint32_t freq = globalSettings.vfoB.frequency;
ltoa(freq,b,10);
morseText(b);
break;
}
case BUTTON_80:
@ -851,12 +885,23 @@ void doCommands(){
active_delay(50);
active_delay(50); //debounce
Button button;
memcpy_P(&button, &(btn_set[select/10]), sizeof(Button));
morseLetter(button.morse);
int8_t morse_status = 0;
button.morse_status(&morse_status);
if(morse_status){
if(morse_status > 0){
morseBool(true);
}
else{
morseBool(false);
}
}
while (true){
//check if the knob's button was pressed
if (btnDown()){
Button button;
memcpy_P(&button, &(btn_set[select/10]), sizeof(Button));
doCommand(&button);
//unfocus the buttons
@ -889,11 +934,26 @@ void doCommands(){
if (prev_button == select / 10)
continue;
//we are on a new button
drawFocus(prev_button, COLOR_INACTIVE_BORDER);
drawFocus(select/10, COLOR_ACTIVE_BORDER);
prev_button = select/10;
//we are on a new button
drawFocus(prev_button, COLOR_INACTIVE_BORDER);
drawFocus(select/10, COLOR_ACTIVE_BORDER);
memcpy_P(&button, &(btn_set[select/10]), sizeof(Button));
morseLetter(button.morse);
morse_status = 0;
button.morse_status(&morse_status);
Serial.println((uint16_t)button.morse_status);
Serial.println(morse_status);
if(morse_status){
if(morse_status > 0){
morseBool(true);
}
else{
morseBool(false);
}
}
enc_read();//Clear any rotation that was done while the letter was playing
prev_button = select/10;
}
// guiUpdate();

View File

@ -30,10 +30,11 @@
* Si5351 object to control the clocks.
*/
#include <Wire.h>
#include "morse.h"
#include "nano_gui.h"
#include "settings.h"
#include "setup.h"
#include "ubitx.h"
#include "nano_gui.h"
/**
* The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory.
@ -65,8 +66,6 @@ unsigned char doingCAT = 0;
void active_delay(int delay_by){
unsigned long timeStart = millis();
while (millis() - timeStart <= (unsigned long)delay_by) {
delay(10);
//Background Work
checkCAT();
}
}
@ -320,7 +319,15 @@ void checkButton(){
active_delay(10);
downTime++;
if (downTime > 300){
doSetup2();
if(!globalSettings.morseMenuOn){
globalSettings.morseMenuOn = true;//set before playing
morseLetter(2);
}
else{
morseLetter(4);
globalSettings.morseMenuOn = false;//unset after playing
}
SaveSettingsToEeprom();
return;
}
}