Merge pull request #3 from reedbn/menu-refactor

Menu refactor
This commit is contained in:
reedbn 2020-01-19 22:36:37 -08:00 committed by GitHub
commit 59347af9ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 534 additions and 439 deletions

View File

@ -145,6 +145,7 @@ public:
static void drawChar(coord_t x, coord_t y, unsigned char c, color_t color, color_t bg, uint8_t size);
static void drawCharGFX(coord_t x, coord_t y, unsigned char c, color_t color, color_t bg, uint8_t size);
static inline void setCursor(coord_t x, coord_t y);
static inline void setBound(coord_t x, coord_t y);
static inline void setTextColor(color_t c);
static inline void setTextColor(color_t c, color_t bg);
static inline void setTextSize(uint8_t s);
@ -157,8 +158,8 @@ public:
static inline uint8_t getRotation() __attribute__ ((always_inline)) { return rotation; }
static inline coord_t getCursorX() __attribute__ ((always_inline)) { return cursor_x; }
static inline coord_t getCursorY() __attribute__ ((always_inline)) { return cursor_y; }
static inline void getTextBounds(char *string, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
static inline void getTextBounds(const __FlashStringHelper *s, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
static inline void getTextBounds(char *string, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi = _width);
static inline void getTextBounds(const __FlashStringHelper *s, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi = _width);
virtual size_t write(uint8_t); // used by Arduino "Print.h" (and the one required virtual function)
@ -167,6 +168,7 @@ protected:
static coord_t WIDTH, HEIGHT; // This is the 'raw' display w/h - never changes
static coord_t _width, _height; // Display w/h as modified by current rotation
static coord_t cursor_x, cursor_y;
static coord_t bound_x1, bound_x2;
static color_t textcolor, textbgcolor;
static uint8_t textsize;
static uint8_t rotation;
@ -216,6 +218,10 @@ int16_t PDQ_GFX<HW>::cursor_x;
template<class HW>
int16_t PDQ_GFX<HW>::cursor_y;
template<class HW>
int16_t PDQ_GFX<HW>::bound_x1;
template<class HW>
int16_t PDQ_GFX<HW>::bound_x2;
template<class HW>
color_t PDQ_GFX<HW>::textcolor;
template<class HW>
color_t PDQ_GFX<HW>::textbgcolor;
@ -239,6 +245,8 @@ PDQ_GFX<HW>::PDQ_GFX(coord_t w, coord_t h)
_height = (int16_t)h;
cursor_x = 0;
cursor_y = 0;
bound_x1 = 0;
bound_x2 = WIDTH;
rotation = 0;
textsize = 1;
textcolor = 0xffff;
@ -740,7 +748,7 @@ size_t PDQ_GFX<HW>::write(uint8_t c)
{
if(c == '\n')
{
cursor_x = 0;
cursor_x = bound_x1;
cursor_y += (coord_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
}
else if (c != '\r')
@ -756,10 +764,10 @@ size_t PDQ_GFX<HW>::write(uint8_t c)
if ((w > 0) && (h > 0))
{
coord_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic
if(wrap && ((cursor_x + textsize * (xo + w)) >= _width))
if(wrap && ((cursor_x + textsize * (xo + w)) >= bound_x2))
{
// Drawing character would go off right edge; wrap to new line
cursor_x = 0;
cursor_x = bound_x1;
cursor_y += (coord_t)textsize *
(uint8_t)pgm_read_byte(&gfxFont->yAdvance);
}
@ -970,6 +978,13 @@ void PDQ_GFX<HW>::setCursor(coord_t x, coord_t y)
cursor_y = (int16_t)y;
}
template<class HW>
void PDQ_GFX<HW>::setBound(coord_t x1, coord_t x2)
{
bound_x1 = (int16_t)x1;
bound_x2 = (int16_t)x2;
}
template<class HW>
void PDQ_GFX<HW>::setTextSize(uint8_t s)
{
@ -1046,10 +1061,13 @@ void PDQ_GFX<HW>::setFont(const GFXfont *f)
// Pass string and a cursor position, returns UL corner and W,H.
template<class HW>
void PDQ_GFX<HW>::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
void PDQ_GFX<HW>::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi)
{
uint8_t c; // Current character
coord_t xs = x;
coord_t xe = xs+wi;
*x1 = x;
*y1 = y;
*w = *h = 0;
@ -1080,9 +1098,9 @@ void PDQ_GFX<HW>::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, in
xa = pgm_read_byte(&glyph->xAdvance);
xo = pgm_read_byte(&glyph->xOffset);
yo = pgm_read_byte(&glyph->yOffset);
if (wrap && ((x + (((int16_t)xo + gw) * ts)) >= _width)) // Line wrap
if (wrap && ((x + (((int16_t)xo + gw) * ts)) >= xe)) // Line wrap
{
x = 0; // Reset x to 0
x = xs; // Reset x to 0
y += ya; // Advance y by 1 line
}
gx1 = x + xo * ts;
@ -1103,7 +1121,7 @@ void PDQ_GFX<HW>::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, in
}
else // Newline
{
x = 0; // Reset x
x = xs; // Reset x
y += ya; // Advance y by 1 line
}
}
@ -1158,10 +1176,12 @@ void PDQ_GFX<HW>::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, in
// Same as above, but for PROGMEM strings
template<class HW>
void PDQ_GFX<HW>::getTextBounds(const __FlashStringHelper *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
void PDQ_GFX<HW>::getTextBounds(const __FlashStringHelper *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi)
{
uint8_t *s = (uint8_t *)str;
uint8_t c;
coord_t xs = x;
coord_t xe = xs+wi;
*x1 = x;
*y1 = y;
@ -1194,9 +1214,9 @@ void PDQ_GFX<HW>::getTextBounds(const __FlashStringHelper *str, coord_t x, coord
xa = pgm_read_byte(&glyph->xAdvance);
xo = pgm_read_byte(&glyph->xOffset);
yo = pgm_read_byte(&glyph->yOffset);
if (wrap && ((x + (((int16_t)xo + gw) * ts)) >= _width)) // Line wrap
if (wrap && ((x + (((int16_t)xo + gw) * ts)) >= xe)) // Line wrap
{
x = 0; // Reset x to 0
x = xs; // Reset x to 0
y += ya; // Advance y by 1 line
}
gx1 = x + xo * ts;
@ -1217,7 +1237,7 @@ void PDQ_GFX<HW>::getTextBounds(const __FlashStringHelper *str, coord_t x, coord
}
else // Newline
{
x = 0; // Reset x
x = xs; // Reset x
y += ya; // Advance y by 1 line
}
}

View File

@ -56,12 +56,12 @@ static const PROGMEM struct Morse morse_table[] = {
{'?', 0x8c}, // 10001100
};
static void morseLetter(char c){
static void morseLetter(char c, uint16_t dit_duration_ms){
unsigned char mask = 0x80;
//handle space character as three dashes
if (c == ' '){
active_delay(9 * globalSettings.cwDitDurationMs);
active_delay(7 * dit_duration_ms);
//Serial.print(' ');
return;
}
@ -81,36 +81,28 @@ static void morseLetter(char c){
while(mask){
tone(CW_TONE, globalSettings.cwSideToneFreq,10000);
if (mask & code){
delay(3 * globalSettings.cwDitDurationMs);
delay(3 * dit_duration_ms);
//Serial.print('-');
}
else{
delay(globalSettings.cwDitDurationMs);
delay(dit_duration_ms);
//Serial.print('.');
}
//Serial.print('#');
noTone(CW_TONE);
delay(globalSettings.cwDitDurationMs); // space between dots and dashes
delay(dit_duration_ms); // space between dots and dashes
mask = mask >> 1;
}
//Serial.println('@');
delay(2*globalSettings.cwDitDurationMs); // space between letters is a dash (3 dots), one dot's space has already been sent
delay(2*dit_duration_ms); // space between letters is a dash (3 dots), one dot's space has already been sent
break;//We've played the letter, so don't bother checking the rest of the list
}
}
}
void morseText(char *text){
// while (1){
noTone(CW_TONE);
delay(1000);
tone(CW_TONE, 600);
delay(1000);
// }
//Serial.println(globalSettings.cwSideToneFreq);
void morseText(char *text, uint16_t dit_duration_ms){
while(*text){
morseLetter(*text++);
morseLetter(*text++, dit_duration_ms);
}
}

View File

@ -1,3 +1,3 @@
#include "settings.h"
//sends out morse code at the speed set by cwSpeed
extern int cwSpeed; //this is actuall the dot period in milliseconds
void morseText(char *text);
void morseText(char *text, uint16_t dit_duration_ms = globalSettings.cwDitDurationMs);

View File

@ -178,7 +178,7 @@ void displayInit(void){
tft.begin();
tft.setFont(ubitx_font);
tft.setTextWrap(false);
tft.setTextWrap(true);
tft.setTextColor(DISPLAY_GREEN,DISPLAY_BLACK);
tft.setTextSize(1);
tft.setRotation(1);
@ -217,6 +217,14 @@ void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t
void displayRawText(char *text, int x1, int y1, int color, int background){
tft.setTextColor(color,background);
tft.setCursor(x1,y1);
tft.setBound(0,320);
tft.print(text);
}
void displayRawText(char *text, int x1, int y1, int w, int color, int background){
tft.setTextColor(color,background);
tft.setCursor(x1,y1);
tft.setBound(x1,x1+w);
tft.print(text);
}
@ -228,10 +236,10 @@ void displayText(char *text, int x1, int y1, int w, int h, int color, int backgr
int16_t y1_out;
uint16_t width_out;
uint16_t height_out;
tft.getTextBounds(text,x1,y1,&x1_out,&y1_out,&width_out,&height_out);
x1 += (w - ( width_out + (x1_out-x1)))/2;
y1 += h - (h - height_out)/2;
displayRawText(text,x1,y1,color,background);
tft.getTextBounds(text,x1,y1,&x1_out,&y1_out,&width_out,&height_out,w);
x1 += (w - ( (int32_t)width_out + (x1_out-x1)))/2;
y1 += (ubitx_font->yAdvance + h - ( (int32_t)height_out + (y1_out-y1)))/2;
displayRawText(text,x1,y1,w,color,background);
}
void setupTouch(){

View File

@ -23,7 +23,6 @@ void formatFreq(uint32_t freq, char* buff, uint16_t buff_size);
/* touch functions */
boolean readTouch();
void setupTouch();
void scaleTouch(struct Point *p);
// Color definitions

687
setup.cpp
View File

@ -1,9 +1,9 @@
#include <Arduino.h>
#include <EEPROM.h>
#include "morse.h"
#include "nano_gui.h"
#include "setup.h"
#include "settings.h"
#include "ubitx.h"
#include "nano_gui.h"
/** Menus
* The Radio menus are accessed by tapping on the function button.
@ -18,13 +18,6 @@
* - If the menu item is NOT clicked on, then the menu's prompt is to be displayed
*/
void setupExit(){
menuOn = 0;
}
//this is used by the si5351 routines in the ubitx_5351 file
extern uint32_t si5351bx_vcoa;
static const unsigned int COLOR_TEXT = DISPLAY_WHITE;
static const unsigned int COLOR_BACKGROUND = DISPLAY_BLACK;
static const unsigned int COLOR_TITLE_BACKGROUND = DISPLAY_NAVY;
@ -58,276 +51,460 @@ static const unsigned int LAYOUT_SETTING_VALUE_Y = LAYOUT_ITEM_Y + 3*LAYOUT_ITEM
static const unsigned int LAYOUT_SETTING_VALUE_WIDTH = LAYOUT_ITEM_WIDTH;
static const unsigned int LAYOUT_SETTING_VALUE_HEIGHT = LAYOUT_ITEM_HEIGHT;
static const unsigned int LAYOUT_INSTRUCTION_TEXT_X = 20;
static const unsigned int LAYOUT_INSTRUCTION_TEXT_Y = LAYOUT_ITEM_Y + 5*LAYOUT_ITEM_PITCH_Y;
static const unsigned int LAYOUT_INSTRUCTION_TEXT_WIDTH = LAYOUT_ITEM_WIDTH;
static const unsigned int LAYOUT_INSTRUCTION_TEXT_HEIGHT = LAYOUT_ITEM_HEIGHT;
static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_X = 20;
static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_Y = LAYOUT_ITEM_Y;
static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_WIDTH = LAYOUT_ITEM_WIDTH;
static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_HEIGHT = LAYOUT_SETTING_VALUE_Y - LAYOUT_ITEM_Y - 1;
void displayDialog(const __FlashStringHelper* title, const __FlashStringHelper* instructions){
strcpy_P(b,(const char*)title);
strcpy_P(c,(const char*)instructions);
static const unsigned int LAYOUT_CONFIRM_TEXT_X = 20;
static const unsigned int LAYOUT_CONFIRM_TEXT_Y = LAYOUT_ITEM_Y + 5*LAYOUT_ITEM_PITCH_Y;
static const unsigned int LAYOUT_CONFIRM_TEXT_WIDTH = LAYOUT_ITEM_WIDTH;
static const unsigned int LAYOUT_CONFIRM_TEXT_HEIGHT = LAYOUT_ITEM_HEIGHT;
void displayDialog(const char* title,
const char* instructions){
displayClear(COLOR_BACKGROUND);
displayRect(LAYOUT_OUTER_BORDER_X,LAYOUT_OUTER_BORDER_Y,LAYOUT_OUTER_BORDER_WIDTH,LAYOUT_OUTER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER);
displayRect(LAYOUT_INNER_BORDER_X,LAYOUT_INNER_BORDER_Y,LAYOUT_INNER_BORDER_WIDTH,LAYOUT_INNER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER);
strncpy_P(b,title,sizeof(b));
displayText(b, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER);
displayText(c, LAYOUT_INSTRUCTION_TEXT_X, LAYOUT_INSTRUCTION_TEXT_Y, LAYOUT_INSTRUCTION_TEXT_WIDTH, LAYOUT_INSTRUCTION_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
strncpy_P(b,instructions,sizeof(b));
displayText(b, LAYOUT_INSTRUCTIONS_TEXT_X, LAYOUT_INSTRUCTIONS_TEXT_Y, LAYOUT_INSTRUCTIONS_TEXT_WIDTH, LAYOUT_INSTRUCTIONS_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
strncpy_P(b,(const char*)F("Push Tune to Save"),sizeof(b));
displayText(b, LAYOUT_CONFIRM_TEXT_X, LAYOUT_CONFIRM_TEXT_Y, LAYOUT_CONFIRM_TEXT_WIDTH, LAYOUT_CONFIRM_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
}
void printCarrierFreq(unsigned long freq)
struct SettingScreen_t {
const char* const Title;
const char* const AdditionalText;
const uint16_t KnobDivider;
const int16_t StepSize;//int so that it can be negative
void (*Initialize)(long int* start_value_out);
void (*Validate)(const long int candidate_value_in, long int* validated_value_out);
void (*OnValueChange)(const long int new_value, char* buff_out, const size_t buff_out_size);
void (*Finalize)(const long int final_value);
};
void runSetting(const SettingScreen_t* const p_screen)
{
formatFreq(freq,c,sizeof(c));
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND);
}
SettingScreen_t screen = {0};
memcpy_P(&screen,p_screen,sizeof(screen));
displayDialog(screen.Title,
screen.AdditionalText);
void setupFreq(){
displayDialog(F("Set Frequency"),F("Push TUNE to Save"));
//round off the the nearest khz
{
uint32_t freq = GetActiveVfoFreq();
freq = (freq/1000l)* 1000l;
setFrequency(freq);
//Wait for button to stop being pressed
while(btnDown()){
active_delay(10);
}
active_delay(10);
strcpy_P(c,(const char*)F("You should have a"));
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
strcpy_P(c,(const char*)F("signal exactly at"));
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 1*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
ltoa(GetActiveVfoFreq()/1000L, c, 10);
strcat_P(c,(const char*)F(" KHz"));
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 2*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
strcpy_P(c,(const char*)F("Rotate to zerobeat"));
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 4*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
ltoa(globalSettings.oscillatorCal, b, 10);
long int raw_value = 0;
long int last_value = 0;
screen.Initialize(&last_value);
screen.OnValueChange(last_value,b,sizeof(b));
displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND);
//keep clear of any previous button press
while (btnDown())
active_delay(100);
active_delay(100);
raw_value = last_value * (int32_t)screen.KnobDivider;
while (!btnDown())
{
int knob = enc_read();
if(knob != 0){
globalSettings.oscillatorCal += knob * 875;
raw_value += knob * screen.StepSize;
}
else{
continue; //don't update the frequency or the display
}
si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the carrier oscillator anyway, cw tx switches it off
si5351_set_calibration(globalSettings.oscillatorCal);
setFrequency(GetActiveVfoFreq());
ltoa(globalSettings.oscillatorCal, b, 10);
displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND);
}
SaveSettingsToEeprom();
initOscillators();
si5351_set_calibration(globalSettings.oscillatorCal);
setFrequency(GetActiveVfoFreq());
//debounce and delay
while(btnDown())
active_delay(50);
active_delay(100);
}
void setupBFO(){
displayDialog(F("Set BFO"),F("Press TUNE to Save"));
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
printCarrierFreq(globalSettings.usbCarrierFreq);
while (!btnDown()){
int knob = enc_read();
if(knob != 0){
globalSettings.usbCarrierFreq -= 50 * knob;
}
else{
continue; //don't update the frequency or the display
}
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
setFrequency(GetActiveVfoFreq());
printCarrierFreq(globalSettings.usbCarrierFreq);
active_delay(100);
}
SaveSettingsToEeprom();
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
setFrequency(GetActiveVfoFreq());
}
void setupCwDelay(){
int knob = 0;
int prev_cw_delay;
displayDialog(F("Set CW T/R Delay"),F("Press tune to Save"));
active_delay(500);
prev_cw_delay = globalSettings.cwActiveTimeoutMs;
ltoa(globalSettings.cwActiveTimeoutMs, b, 10);
strcat_P(b,(const char*)F(" msec"));
displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
while (!btnDown()){
knob = enc_read();
if (knob < 0 && globalSettings.cwActiveTimeoutMs > 100)
globalSettings.cwActiveTimeoutMs -= 100;
else if (knob > 0 && globalSettings.cwActiveTimeoutMs < 1000)
globalSettings.cwActiveTimeoutMs += 100;
else
continue; //don't update the frequency or the display
ltoa(globalSettings.cwActiveTimeoutMs, b, 10);
strcat_P(b,(const char*)F(" msec"));
displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
}
SaveSettingsToEeprom();
active_delay(500);
setupExit();
}
void setupKeyer(){
displayDialog(F("Set CW Keyer"),F("Press tune to Save"));
if(KeyerMode_e::KEYER_STRAIGHT == globalSettings.keyerMode){
strcpy_P(c,(const char*)F("< Hand Key >"));
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
}
else if(KeyerMode_e::KEYER_IAMBIC_A == globalSettings.keyerMode){
strcpy_P(c,(const char*)F("< Iambic A >"));
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
}
else{
strcpy_P(c,(const char*)F("< Iambic B >"));
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
}
int knob = 0;
uint32_t tmp_mode = globalSettings.keyerMode;
while (!btnDown())
{
knob = enc_read();
if(knob == 0){
active_delay(50);
continue;
}
if(knob < 0 && tmp_mode > KeyerMode_e::KEYER_STRAIGHT){
tmp_mode--;
}
if(knob > 0 && tmp_mode < KeyerMode_e::KEYER_IAMBIC_B){
tmp_mode++;
const long int candidate_value = raw_value / (int32_t)screen.KnobDivider;
long int value = 0;
screen.Validate(candidate_value,&value);
//If we're going out of bounds, prevent the raw value from going too far out
if(candidate_value != value){
raw_value = value * (int32_t)screen.KnobDivider;
}
if (KeyerMode_e::KEYER_STRAIGHT == tmp_mode){
strcpy_P(c,(const char*)F("< Hand Key >"));
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
if(value == last_value){
continue;
}
else if(KeyerMode_e::KEYER_IAMBIC_A == tmp_mode){
strcpy_P(c,(const char*)F("< Iambic A >"));
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
}
else if (KeyerMode_e::KEYER_IAMBIC_B == tmp_mode){
strcpy_P(c,(const char*)F("< Iambic B >"));
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
else{
screen.OnValueChange(value,b,sizeof(b));
displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND);
last_value = value;
}
}
active_delay(500);
screen.Finalize(last_value);
}
globalSettings.keyerMode = tmp_mode;
#define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val))
//Local Oscillator
void ssLocalOscInitialize(long int* start_value_out){
{
uint32_t freq = GetActiveVfoFreq();
freq = (freq/1000L) * 1000L;//round off the current frequency the nearest kHz
setFrequency(freq);
si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the carrier oscillator, cw tx switches it off
}
*start_value_out = globalSettings.oscillatorCal;
}
void ssLocalOscValidate(const long int candidate_value_in, long int* validated_value_out)
{
*validated_value_out = candidate_value_in;//No check - allow anything
}
void ssLocalOscChange(const long int new_value, char* buff_out, const size_t buff_out_size)
{
si5351_set_calibration(new_value);
setFrequency(GetActiveVfoFreq());
const long int u = abs(new_value);
if(new_value != u){
strncpy_P(buff_out,(const char*)F("-"),buff_out_size);
++buff_out;
}
formatFreq(u,buff_out,buff_out_size - strlen(buff_out));
strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out));
}
void ssLocalOscFinalize(const long int final_value)
{
globalSettings.oscillatorCal = final_value;
SaveSettingsToEeprom();
setupExit();
si5351_set_calibration(globalSettings.oscillatorCal);
setFrequency(GetActiveVfoFreq());
}
const char MI_SET_FREQ [] PROGMEM = "Set Freq...";
const char MI_SET_BFO [] PROGMEM = "Set BFO...";
const char MI_CW_DELAY [] PROGMEM = "CW Delay...";
const char MI_CW_KEYER [] PROGMEM = "CW Keyer...";
const char MI_TOUCH [] PROGMEM = "Touch Screen...";
const char MI_EXIT [] PROGMEM = "Exit";
enum MenuIds {
MENU_SET_FREQ,
MENU_SET_BFO,
MENU_CW_DELAY,
MENU_CW_KEYER,
MENU_TOUCH,
MENU_EXIT,
MENU_TOTAL
const char SS_LOCAL_OSC_T [] PROGMEM = "Local Oscillator";
const char SS_LOCAL_OSC_A [] PROGMEM = "Exit menu, tune so that the\ndial displays the desired freq,\nthen tune here until the\nsignal is zerobeat";
const SettingScreen_t ssLocalOsc PROGMEM = {
SS_LOCAL_OSC_T,
SS_LOCAL_OSC_A,
1,
875,
ssLocalOscInitialize,
ssLocalOscValidate,
ssLocalOscChange,
ssLocalOscFinalize
};
void runLocalOscSetting(){runSetting(&ssLocalOsc);}
const char* const menuItems [MENU_TOTAL] PROGMEM {
MI_SET_FREQ,
MI_SET_BFO,
MI_CW_DELAY,
MI_CW_KEYER,
MI_TOUCH,
MI_EXIT
//BFO
void ssBfoInitialize(long int* start_value_out){
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
*start_value_out = globalSettings.usbCarrierFreq;
}
void ssBfoValidate(const long int candidate_value_in, long int* validated_value_out)
{
*validated_value_out = LIMIT(candidate_value_in,11048000L,11060000L);
}
void ssBfoChange(const long int new_value, char* buff_out, const size_t buff_out_size)
{
globalSettings.usbCarrierFreq = new_value;
setFrequency(GetActiveVfoFreq());
si5351bx_setfreq(0, new_value);
formatFreq(new_value,buff_out,buff_out_size);
strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out));
}
void ssBfoFinalize(const long int final_value)
{
globalSettings.usbCarrierFreq = final_value;
SaveSettingsToEeprom();
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
setFrequency(GetActiveVfoFreq());
}
const char SS_BFO_T [] PROGMEM = "Beat Frequency Osc (BFO)";
const char SS_BFO_A [] PROGMEM = "Exit menu, tune to an unused\nfrequency, then tune here\nuntil the audio is between\n300-3000Hz";
const SettingScreen_t ssBfo PROGMEM = {
SS_BFO_T,
SS_BFO_A,
1,
-50,//Negative to make dial more intuitive: turning clockwise increases the perceived audio frequency
ssBfoInitialize,
ssBfoValidate,
ssBfoChange,
ssBfoFinalize
};
void runBfoSetting(){runSetting(&ssBfo);}
void drawSetupMenu(){
displayClear(COLOR_BACKGROUND);
strcpy_P(b,(const char*)F("Setup"));
displayText(b, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER);
for(unsigned int i = 0; i < MENU_TOTAL; ++i){
strcpy_P(b,(const char*)pgm_read_word(&(menuItems[i])));
displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + i*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER);
//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)
{
*start_value_out = globalSettings.cwSideToneFreq;
}
void ssCwToneValidate(const long int candidate_value_in, long int* validated_value_out)
{
*validated_value_out = LIMIT(candidate_value_in,100,2000);
}
void ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_out_size)
{
globalSettings.cwSideToneFreq = new_value;
tone(CW_TONE, globalSettings.cwSideToneFreq);
ltoa(globalSettings.cwSideToneFreq,buff_out,10);
strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out));
}
void ssCwToneFinalize(const long int final_value)
{
noTone(CW_TONE);
globalSettings.cwSideToneFreq = final_value;
SaveSettingsToEeprom();
}
const char SS_CW_TONE_T [] PROGMEM = "CW Tone Frequency";
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,
SS_CW_TONE_A,
1,
10,
ssCwToneInitialize,
ssCwToneValidate,
ssCwToneChange,
ssCwToneFinalize
};
void runToneSetting(){runSetting(&ssTone);}
//CW Switch Delay
void ssCwSwitchDelayInitialize(long int* start_value_out)
{
*start_value_out = globalSettings.cwActiveTimeoutMs;
}
void ssCwSwitchDelayValidate(const long int candidate_value_in, long int* validated_value_out)
{
*validated_value_out = LIMIT(candidate_value_in,100,1000);
}
void ssCwSwitchDelayChange(const long int new_value, char* buff_out, const size_t buff_out_size)
{
ltoa(new_value,buff_out,10);
strncat_P(buff_out,(const char*)F("ms"),buff_out_size - strlen(buff_out));
}
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_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,
SS_CW_SWITCH_A,
1,
100,
ssCwSwitchDelayInitialize,
ssCwSwitchDelayValidate,
ssCwSwitchDelayChange,
ssCwSwitchDelayFinalize
};
void runCwSwitchDelaySetting(){runSetting(&ssCwSwitchDelay);}
//CW Keyer
void ssKeyerInitialize(long int* start_value_out)
{
*start_value_out = globalSettings.keyerMode;
}
void ssKeyerValidate(const long int candidate_value_in, long int* validated_value_out)
{
*validated_value_out = LIMIT(candidate_value_in,KeyerMode_e::KEYER_STRAIGHT,KeyerMode_e::KEYER_IAMBIC_B);
}
void ssKeyerChange(const long int new_value, char* buff_out, const size_t buff_out_size)
{
if(KeyerMode_e::KEYER_STRAIGHT == new_value){
strncpy_P(buff_out,(const char*)F("< Hand Key >"),buff_out_size);
}
else if(KeyerMode_e::KEYER_IAMBIC_A == new_value){
strncpy_P(buff_out,(const char*)F("< Iambic A >"),buff_out_size);
}
else{
strncpy_P(buff_out,(const char*)F("< Iambic B >"),buff_out_size);
}
}
void ssKeyerFinalize(const long int final_value)
{
globalSettings.keyerMode = final_value;
SaveSettingsToEeprom();
}
const char SS_KEYER_T [] PROGMEM = "CW Keyer/Paddle Type";
const char SS_KEYER_A [] PROGMEM = "Select which type of\nkeyer/paddle is being used";
const SettingScreen_t ssKeyer PROGMEM = {
SS_KEYER_T,
SS_KEYER_A,
10,
1,
ssKeyerInitialize,
ssKeyerValidate,
ssKeyerChange,
ssKeyerFinalize
};
void runKeyerSetting(){runSetting(&ssKeyer);}
void movePuck(int i){
static int prevPuck = 1;//Start value at 1 so that on init, when we get called with 0, we'll update
//Reset all settings
void ssResetAllInitialize(long int* start_value_out)
{
*start_value_out = 0;//Default to NOT resetting
}
void ssResetAllValidate(const long int candidate_value_in, long int* validated_value_out)
{
*validated_value_out = LIMIT(candidate_value_in,0,1);
}
void ssResetAllChange(const long int new_value, char* buff_out, const size_t buff_out_size)
{
if(new_value){
strncpy_P(buff_out,(const char*)F("Yes"),buff_out_size);
}
else{
strncpy_P(buff_out,(const char*)F("No"),buff_out_size);
}
}
void ssResetAllFinalize(const long int final_value)
{
if(final_value){
LoadDefaultSettings();
SaveSettingsToEeprom();
setup();
}
}
const char SS_RESET_ALL_T [] PROGMEM = "Reset All Cals/Settings";
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,
SS_RESET_ALL_A,
20,
1,
ssResetAllInitialize,
ssResetAllValidate,
ssResetAllChange,
ssResetAllFinalize
};
void runResetAllSetting(){runSetting(&ssResetAll);}
struct MenuItem_t {
const char* const ItemName;
const void (*OnSelect)();
};
void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items);
#define RUN_MENU(menu) runMenu(menu,sizeof(menu)/sizeof(menu[0]))
const char MT_CAL [] PROGMEM = "Calibrations";
const char MI_TOUCH [] PROGMEM = "Touch Screen";
const MenuItem_t calibrationMenu [] PROGMEM {
{MT_CAL,nullptr},//Title
{SS_LOCAL_OSC_T,runLocalOscSetting},
{SS_BFO_T,runBfoSetting},
{MI_TOUCH,setupTouch},
};
void runCalibrationMenu(){RUN_MENU(calibrationMenu);}
const char MT_CW [] PROGMEM = "CW/Morse 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},
};
void runCwMenu(){RUN_MENU(cwMenu);}
const char MT_SETTINGS [] PROGMEM = "Settings";
const MenuItem_t mainMenu [] PROGMEM {
{MT_SETTINGS,nullptr},//Title
{MT_CAL,runCalibrationMenu},
{MT_CW,runCwMenu},
{SS_RESET_ALL_T,runResetAllSetting},
};
const char MI_EXIT [] PROGMEM = "Exit";
const MenuItem_t exitMenu PROGMEM = {MI_EXIT,nullptr};
void drawMenu(const MenuItem_t* const items, const uint16_t num_items)
{
displayClear(COLOR_BACKGROUND);
MenuItem_t mi = {"",nullptr};
memcpy_P(&mi,&items[0],sizeof(mi));
strncpy_P(b,mi.ItemName,sizeof(b));
displayText(b, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER);
for(unsigned int i = 1; i < num_items; ++i){
memcpy_P(&mi,&items[i],sizeof(mi));
strncpy_P(b,mi.ItemName,sizeof(b));
displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (i-1)*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER);
}
memcpy_P(&mi,&exitMenu,sizeof(mi));
strncpy_P(b,mi.ItemName,sizeof(b));
displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (num_items-1)*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER);
}
void movePuck(unsigned int old_index, unsigned int new_index)
{
//Don't update if we're already on the right selection
if(prevPuck == i){
if(old_index == new_index){
return;
}
//Clear old
displayRect(LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (prevPuck*LAYOUT_ITEM_PITCH_Y), LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_INACTIVE_BORDER);
else if(((unsigned int)-1) != old_index){
//Clear old
displayRect(LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (old_index*LAYOUT_ITEM_PITCH_Y), LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_INACTIVE_BORDER);
}
//Draw new
displayRect(LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (i*LAYOUT_ITEM_PITCH_Y), LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_ACTIVE_BORDER);
prevPuck = i;
displayRect(LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (new_index*LAYOUT_ITEM_PITCH_Y), LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_ACTIVE_BORDER);
}
void doSetup2(){
void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items)
{
static const unsigned int COUNTS_PER_ITEM = 10;
int select=0, i, btnState;
const unsigned int MAX_KNOB_VALUE = num_items*COUNTS_PER_ITEM - 1;
int knob_sum = 0;
unsigned int old_index = 0;
drawSetupMenu();
movePuck(select);
drawMenu(menu_items,num_items);
movePuck(1,0);//Force draw of puck
//wait for the button to be raised up
while(btnDown())
while(btnDown()){
active_delay(50);
}
active_delay(50); //debounce
menuOn = 2;
while (menuOn){
i = enc_read();
while (true){
knob_sum += enc_read();
if(knob_sum < 0){
knob_sum = 0;
}
else if(MAX_KNOB_VALUE < knob_sum){
knob_sum = MAX_KNOB_VALUE;
}
if (i > 0){
if (select + i < MENU_TOTAL*COUNTS_PER_ITEM)
select += i;
movePuck(select/COUNTS_PER_ITEM);
}
if (i < 0 && select + i >= 0){
select += i; //caught ya, i is already -ve here, so you add it
movePuck(select/COUNTS_PER_ITEM);
}
uint16_t index = knob_sum/COUNTS_PER_ITEM;
movePuck(old_index,index);
old_index = index;
if (!btnDown()){
active_delay(50);
@ -338,50 +515,28 @@ void doSetup2(){
while(btnDown()){
active_delay(50);
}
active_delay(300);
active_delay(50);//debounce
switch(select/COUNTS_PER_ITEM){
case MENU_SET_FREQ:
{
setupFreq();
break;
}
case MENU_SET_BFO:
{
setupBFO();
break;
}
case MENU_CW_DELAY:
{
setupCwDelay();
break;
}
case MENU_CW_KEYER:
{
setupKeyer();
break;
}
case MENU_TOUCH:
{
setupTouch();
break;
}
case MENU_EXIT:
default:
{
menuOn = 0;
break;
}
}//switch
//redraw
drawSetupMenu();
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
mi.OnSelect();
drawMenu(menu_items,num_items);//Need to re-render, since whatever ran just now is assumed to have drawn something
old_index = -1;//Force redraw
}
else{
break;
}
}
//debounce the button
while(btnDown())
while(btnDown()){
active_delay(50);
active_delay(50);
}
active_delay(50);//debounce
}
checkCAT();
void doSetup2(){
RUN_MENU(mainMenu);
guiUpdate();
}

6
setup.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
void doSetup2(); //main setup function, displays the setup menu, calls various dialog boxes
void setupTouch();
void runLocalOscSetting();
void runBfoSetting();

11
ubitx.h
View File

@ -56,7 +56,7 @@ it uses an ILI9341 display controller and an XPT2046 touch controller.
* the input and output from the USB port. We must keep a count of the bytes used while reading
* the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable.
*/
extern char c[30], b[30];
extern char c[30], b[128];
/**
* The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig.
@ -92,10 +92,6 @@ extern char c[30], b[30];
#define HIGHEST_FREQ (30000000l)
static const uint32_t THRESHOLD_USB_LSB = 10000000L;
extern unsigned long firstIF;
extern uint8_t menuOn;
/* these are functions implemented in the main file named as ubitx_xxx.ino */
void active_delay(int delay_by);
void saveVFOs();
@ -122,11 +118,6 @@ void drawTx();
//are useful to concatanate the values with text like "Set Freq to " x " KHz"
int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* prefix, char *postfix);
//functions of the setup menu. implemented in seteup.cpp
void doSetup2(); //main setup function, displays the setup menu, calls various dialog boxes
void setupBFO();
void setupFreq();
//main functions to check if any button is pressed and other user interface events
void doCommands(); //does the commands with encoder to jump from button to button
void checkTouch(); //does the commands with a touch on the buttons

View File

@ -123,13 +123,6 @@ void catReadEEPRom(void)
//for remove warnings
byte temp0 = cat[0];
byte temp1 = cat[1];
/*
itoa((int) cat[0], b, 16);
strcat(b, ":");
itoa((int) cat[1], c, 16);
strcat(b, c);
printLine2(b);
*/
cat[0] = 0;
cat[1] = 0;
@ -385,10 +378,6 @@ void processCATCommand2(byte* cmd) {
default:
//somehow, get this to print the four bytes
ultoa(*((unsigned long *)cmd), c, 16);
/*itoa(cmd[4], b, 16);
strcat(b, ">");
strcat(b, c);
printLine2(b);*/
response[0] = 0x00;
Serial.write(response[0]);
}

View File

@ -1,7 +1,7 @@
#include <Arduino.h>
#include <EEPROM.h>
#include "morse.h"
#include "settings.h"
#include "setup.h"
#include "ubitx.h"
#include "nano_gui.h"
@ -65,8 +65,8 @@ enum btn_set_e {
BUTTON_17,
BUTTON_15,
BUTTON_10,
BUTTON_WPM,
BUTTON_TON,
BUTTON_BLANK_1,
BUTTON_MNU,
BUTTON_FRQ,
BUTTON_TOTAL
};
@ -85,7 +85,7 @@ constexpr Button btn_set[BUTTON_TOTAL] PROGMEM = {
{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", 'M'},
{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 + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_80, "80", '8'},
@ -96,8 +96,8 @@ constexpr Button btn_set[BUTTON_TOTAL] PROGMEM = {
{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_WPM, "WPM", 'W'},
{LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_TON, "TON", 'T'},
{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, "MNU", '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'},
};
@ -165,10 +165,10 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, const
active_delay(200);
knob_value = initial;
strcpy_P(b,(const char*)prefix);
strncpy_P(b,(const char*)prefix,sizeof(b));
itoa(knob_value, c, 10);
strcat(b, c);
strcat_P(b, (const char*)postfix);
strncat(b, c, sizeof(b) - strlen(b));
strncat_P(b, (const char*)postfix, sizeof(b) - strlen(b));
drawCommandbar(b);
while(!btnDown() && digitalRead(PTT) == HIGH){
@ -179,10 +179,10 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, const
if (knob_value < maximum && knob > 0)
knob_value += step_size;
strcpy_P(b,(const char*)prefix);
strncpy_P(b,(const char*)prefix,sizeof(b));
itoa(knob_value, c, 10);
strcat(b, c);
strcat_P(b,(const char*)postfix);
strncat(b, c, sizeof(b) - strlen(b));
strncat_P(b,(const char*)postfix, sizeof(b) - strlen(b));
drawCommandbar(b);
}
checkCAT();
@ -334,8 +334,8 @@ void displayRIT(){
c[0] = 0;
displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND);
if(globalSettings.ritOn){
strcpy_P(c,(const char*)F("TX:"));
formatFreq(globalSettings.ritFrequency, c+3, sizeof(c)-3);
strncpy_P(c,(const char*)F("TX:"),sizeof(c));
formatFreq(globalSettings.ritFrequency, c+3, sizeof(c)-strlen(c));
if (VFO_A == globalSettings.activeVfo)
displayText(c, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
else
@ -349,9 +349,9 @@ void fastTune(){
active_delay(50);
active_delay(300);
strcpy_P(c,(const char*)F("Fast tune"));
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);
while(1){
while(true){
checkCAT();
//exit after debouncing the btnDown
@ -471,8 +471,8 @@ void enterFreq(){
}//switch
}//if button hit test
}// end of the button scanning loop
strcpy(b, c);
strcat_P(b,(const char*)F(" KHz"));
strncpy(b, c, sizeof(b));
strncat_P(b,(const char*)F(" KHz"),sizeof(b) - strlen(b));
displayText(b, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
active_delay(300);
while(readTouch())
@ -481,21 +481,21 @@ void enterFreq(){
}
void drawCWStatus(){
strcpy_P(b,(const char*)F(" cw: "));
strncpy_P(b,(const char*)F(" cw: "),sizeof(b));
int wpm = 1200/globalSettings.cwDitDurationMs;
itoa(wpm,c, 10);
strcat(b, c);
strcat_P(b,(const char*)F("wpm, "));
strncat(b, c, sizeof(b) - strlen(b));
strncat_P(b,(const char*)F("wpm, "), sizeof(b) - strlen(b));
itoa(globalSettings.cwSideToneFreq, c, 10);
strcat(b, c);
strcat_P(b,(const char*)F("hz"));
strncat(b, c, sizeof(b) - strlen(b));
strncat_P(b,(const char*)F("hz"), sizeof(b) - strlen(b));
displayText(b, LAYOUT_CW_TEXT_X, LAYOUT_CW_TEXT_Y, LAYOUT_CW_TEXT_WIDTH, LAYOUT_CW_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
}
void drawTx(){
if (globalSettings.txActive){
strcpy_P(b,(const char*)F("TX"));
strncpy_P(b,(const char*)F("TX"), sizeof(b));
displayText(b, LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_BACKGROUND);
}
else{
@ -808,65 +808,6 @@ void switchBand(uint32_t bandfreq){
saveVFOs();
}
void setCwSpeed()
{
int wpm = 1200/globalSettings.cwDitDurationMs;
wpm = getValueByKnob(1, 100, 1, wpm,F("CW: "),F(" WPM"));
globalSettings.cwDitDurationMs = 1200/wpm;
SaveSettingsToEeprom();
active_delay(500);
drawStatusbar();
//printLine2("");
//updateDisplay();
}
void setCwTone(){
int knob = 0;
int prev_sideTone;
tone(CW_TONE, globalSettings.cwSideToneFreq);
itoa(globalSettings.cwSideToneFreq, c, 10);
strcpy_P(b,(const char*)F("CW Tone: "));
strcat(b, c);
strcat_P(b,(const char*)F(" Hz"));
drawCommandbar(b);
//disable all clock 1 and clock 2
while (digitalRead(PTT) == HIGH && !btnDown())
{
knob = enc_read();
if (knob > 0 && globalSettings.cwSideToneFreq < 2000)
globalSettings.cwSideToneFreq += 10;
else if (knob < 0 && globalSettings.cwSideToneFreq > 100 )
globalSettings.cwSideToneFreq -= 10;
else
continue; //don't update the frequency or the display
tone(CW_TONE, globalSettings.cwSideToneFreq);
itoa(globalSettings.cwSideToneFreq, c, 10);
strcpy_P(b,(const char*)F("CW Tone: "));
strcat(b, c);
strcat_P(b,(const char*)F(" Hz"));
drawCommandbar(b);
//printLine2(b);
checkCAT();
active_delay(20);
}
noTone(CW_TONE);
SaveSettingsToEeprom();
b[0] = 0;
drawCommandbar(b);
drawStatusbar();
//printLine2("");
//updateDisplay();
}
void doCommand(Button* button){
//Serial.print(F("Doing command: "));
//Serial.print(button->text);
@ -957,14 +898,9 @@ void doCommand(Button* button){
enterFreq();
break;
}
case BUTTON_WPM:
case BUTTON_MNU:
{
setCwSpeed();
break;
}
case BUTTON_TON:
{
setCwTone();
doSetup2();
break;
}
default:
@ -1017,20 +953,17 @@ void drawFocus(int ibtn, int color){
}
void doCommands(){
int select=0, i, prevButton, btnState;
int select = 0;
int prev_button = 0;
//wait for the button to be raised up
while(btnDown())
active_delay(50);
active_delay(50); //debounce
menuOn = 2;
while (menuOn){
while (true){
//check if the knob's button was pressed
btnState = btnDown();
if (btnState){
if (btnDown()){
Button button;
memcpy_P(&button, &(btn_set[select/10]), sizeof(Button));
@ -1050,27 +983,27 @@ void doCommands(){
return;
}
i = enc_read();
int knob = enc_read();
if (i == 0){
if (knob == 0){
active_delay(50);
continue;
}
if (i > 0){
if (select + i < BUTTON_TOTAL * 10)
select += i;
if (knob > 0){
if (select + knob < BUTTON_TOTAL * 10)
select += knob;
}
if (i < 0 && select + i >= 0)
select += i; //caught ya, i is already -ve here, so you add it
if (knob < 0 && select + knob >= 0)
select += knob; //caught ya, i is already -ve here, so you add it
if (prevButton == select / 10)
if (prev_button == select / 10)
continue;
//we are on a new button
drawFocus(prevButton, COLOR_INACTIVE_BORDER);
drawFocus(prev_button, COLOR_INACTIVE_BORDER);
drawFocus(select/10, COLOR_ACTIVE_BORDER);
prevButton = select/10;
prev_button = select/10;
}
// guiUpdate();

View File

@ -31,6 +31,7 @@
*/
#include <Wire.h>
#include "settings.h"
#include "setup.h"
#include "ubitx.h"
#include "nano_gui.h"
@ -40,16 +41,16 @@
* created in a memory region called the stack. The stack has just a few bytes of space on the Arduino
* if you declare large strings inside functions, they can easily exceed the capacity of the stack
* and mess up your programs.
* We circumvent this by declaring a few global buffers as kitchen counters where we can
* We circumvent this by declaring a few global buffers as kitchen counters where we can
* slice and dice our strings. These strings are mostly used to control the display or handle
* the input and output from the USB port. We must keep a count of the bytes used while reading
* the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable.
*/
char c[30], b[30];
char b[128];
char c[30];
//during CAT commands, we will freeeze the display until CAT is disengaged
unsigned char doingCAT = 0;
byte menuOn = 0; //set to 1 when the menu is being displayed, if a menu item sets it to zero, the menu is exited
/**
@ -463,7 +464,7 @@ void initPorts(){
void setup()
{
Serial.begin(38400);
Serial.flush();
Serial.flush();
initSettings();
displayInit();
@ -473,13 +474,14 @@ void setup()
//Run initial calibration routine if button is pressed during power up
if(btnDown()){
LoadDefaultSettings();
setupTouch();
SetActiveVfoMode(VfoMode_e::VFO_MODE_USB);
setFrequency(10000000l);
setupFreq();
setFrequency(10000000L);
runLocalOscSetting();
SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB);
setFrequency(7100000l);
setupBFO();
setFrequency(7100000L);
runBfoSetting();
}
guiUpdate();