Rough pass at button grids

This commit is contained in:
Reed Nightingale 2020-04-25 19:46:36 -07:00
parent 2db9899d4d
commit 1f97be3263
12 changed files with 347 additions and 298 deletions

View File

@ -1,44 +0,0 @@
#include "button.h"
#include <avr/pgmspace.h>
#include "color_theme.h"
#include "nano_gui.h"
#include "scratch_space.h"
void drawButton(Button* button)
{
uint16_t tc = COLOR_INACTIVE_TEXT;
uint16_t bgc = COLOR_INACTIVE_BACKGROUND;
const uint16_t bdc = COLOR_INACTIVE_BORDER;
switch(button->status())
{
case ButtonStatus_e::Stateless://Fallthrough intended
case ButtonStatus_e::Inactive://Fallthrough intended
default:
{
//Colors are initialized for this, so we're done
break;
}
case ButtonStatus_e::Active:
{
tc = COLOR_ACTIVE_TEXT;
bgc = COLOR_ACTIVE_BACKGROUND;
break;
}
}
if(nullptr != button->text){
strncpy_P(b,button->text,sizeof(b));
}
else if(nullptr != button->text_override){
button->text_override(b,sizeof(b));
}
else{
//Something's messed up
//Serial.println(F("No text for button!"));
return;
}
displayText(b, button->x, button->y, button->w, button->h, tc, bgc, bdc);
}

View File

@ -1,20 +0,0 @@
#pragma once
#include <stdint.h>
enum ButtonStatus_e : uint8_t {
Stateless,
Inactive,
Active
};
struct Button {
int16_t x, y, w, h;
const char* text;//nullptr if text_override should be used
void (*text_override)(char* text_out, const uint16_t max_text_size);//nullptr if text should be used
ButtonStatus_e (*status)();//Used for coloring and morse menu
void (*on_select)();//Action to take when selected
char morse;
};
void drawButton(Button* button);

90
button_grid.cpp Normal file
View File

@ -0,0 +1,90 @@
#include "button_grid.h"
#include <Arduino.h>
#include <avr/pgmspace.h>
#include "color_theme.h"
#include "nano_gui.h"
#include "scratch_space.h"
void drawButton(const ButtonGrid_t *const button_grid_P,
const Button *const button_P)
{
uint16_t tc = COLOR_INACTIVE_TEXT;
uint16_t bgc = COLOR_INACTIVE_BACKGROUND;
const uint16_t bdc = COLOR_INACTIVE_BORDER;
Button button;
memcpy_P(&button,button_P,sizeof(button));
switch(button.status())
{
case ButtonStatus_e::Stateless://Fallthrough intended
case ButtonStatus_e::Inactive://Fallthrough intended
default:
{
//Colors are initialized for this, so we're done
break;
}
case ButtonStatus_e::Active:
{
tc = COLOR_ACTIVE_TEXT;
bgc = COLOR_ACTIVE_BACKGROUND;
break;
}
}
if(nullptr != button.text){
strncpy_P(b,button.text,sizeof(b));
}
else if(nullptr != button.text_override){
button.text_override(b,sizeof(b));
}
else{
//Something's messed up
//Serial.println(F("No text for button!"));
return;
}
ButtonGrid_t button_grid;
memcpy_P(&button_grid,button_grid_P,sizeof(button_grid));
uint8_t button_col = 0;
uint8_t button_row = 0;
bool found_it = false;
for(button_col = 0; button_col < button_grid.num_button_cols && !found_it; ++button_col){
for(button_row = 0; button_row < button_grid.num_button_rows && !found_it; ++button_row){
Button* bp;
memcpy_P(&bp,&(button_grid.buttons_P[button_row*button_grid.num_button_cols + button_col]),sizeof(bp));
if(bp == button_P){
found_it = true;
break;
}
}
if(found_it){
break;
}
}
Serial.print(button_col);Serial.print(",");Serial.print(button_row);Serial.print(" ");Serial.println(b);
displayText(b,
button_col * button_grid.button_pitch_x + button_grid.top_left_x,
button_row * button_grid.button_pitch_y + button_grid.top_left_y,
button_grid.button_width,
button_grid.button_height,
tc, bgc, bdc);
}
void drawButtonGrid(const ButtonGrid_t *const button_grid_P)
{
ButtonGrid_t button_grid;
memcpy_P(&button_grid,button_grid_P,sizeof(button_grid));
Button* bp;
for(uint8_t i = 0; i < button_grid.num_button_rows * button_grid.num_button_cols; ++i){
memcpy_P(&bp, &(button_grid.buttons_P[i]), sizeof(bp));
if(nullptr == bp){
continue;
}
drawButton(button_grid_P,bp);
}
}

33
button_grid.h Normal file
View File

@ -0,0 +1,33 @@
#pragma once
#include <stdint.h>
enum ButtonStatus_e : uint8_t {
Stateless,
Inactive,
Active
};
struct Button {
const char* text;//nullptr if text_override should be used
void (*text_override)(char* text_out, const uint16_t max_text_size);//nullptr if text should be used
ButtonStatus_e (*status)();//Used for coloring and morse menu
void (*on_select)();//Action to take when selected
char morse;
};
struct ButtonGrid_t {
int16_t top_left_x;
int16_t top_left_y;
uint16_t button_width;
uint16_t button_height;
uint16_t button_pitch_x;
uint16_t button_pitch_y;
uint8_t num_button_rows;
uint8_t num_button_cols;
const Button* const* buttons_P;//Expected to be in progmem
};
void drawButton(const ButtonGrid_t *const button_grid_P,
const Button *const button_P);
void drawButtonGrid(const ButtonGrid_t *const button_grid_P);

View File

@ -4,7 +4,7 @@
#include <avr/pgmspace.h>
#include <Arduino.h>
#include "button.h"
#include "button_grid.h"
#include "color_theme.h"
#include "menu_utils.h"
#include "morse.h"
@ -33,13 +33,9 @@ int16_t mainMenuSelectedItemRaw = 0;//Allow negative only for easier checks on w
void drawMainMenu(void)
{
displayClear(COLOR_BACKGROUND);
Button button;
Button* bp;
for(uint8_t i = 0; i < MAIN_MENU_NUM_BUTTONS; ++i){
memcpy_P(&bp, &(mainMenuButtons[i]), sizeof(bp));
memcpy_P(&button,bp,sizeof(button));
drawButton(&button);
}
drawButtonGrid(&mainMenuGrid);
ltoa(GetActiveVfoFreq(),b,10);
morseText(b);
}
@ -65,14 +61,13 @@ void mainMenuTune(int16_t knob)
const uint32_t old_freq = current_freq;
current_freq = new_freq;
Button button;
if(Vfo_e::VFO_A == globalSettings.activeVfo){
memcpy_P(&button,&bVfoA,sizeof(button));
drawButton(&mainMenuVfoGrid,&bVfoA);
}
else{
memcpy_P(&button,&bVfoB,sizeof(button));
drawButton(&mainMenuVfoGrid,&bVfoB);
}
drawButton(&button);
updateBandButtons(old_freq);
}
@ -94,17 +89,17 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button,
{
if(mainMenuSelecting){
uint8_t menu_index = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM;
endSelector(mainMenuSelectedItemRaw,&mainMenuGrid);
Button button;
Button* bp;
memcpy_P(&bp,&(mainMenuButtons[menu_index]),sizeof(bp));
memcpy_P(&bp,&(mainMenuGrid.buttons_P[menu_index]),sizeof(bp));
memcpy_P(&button,bp,sizeof(button));
endSelector(&button);
button.on_select();
}
else{
initSelector(&mainMenuSelectedItemRaw,
mainMenuButtons,
MAIN_MENU_NUM_BUTTONS,
&mainMenuGrid,
MorsePlaybackType_e::PlayChar);
}
mainMenuSelecting = !mainMenuSelecting;
@ -134,7 +129,7 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button,
else if(ButtonPress_e::NotPressed != touch_button){
//We treat long and short presses the same, so no need to have a switch
Button button;
if(findPressedButton(mainMenuButtons,MAIN_MENU_NUM_BUTTONS,&button,touch_point)){
if(findPressedButton(&mainMenuGrid,&button,touch_point)){
button.on_select();
}
else{
@ -146,8 +141,7 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button,
if(mainMenuSelecting){
adjustSelector(&mainMenuSelectedItemRaw,
knob,
mainMenuButtons,
MAIN_MENU_NUM_BUTTONS,
&mainMenuGrid,
MorsePlaybackType_e::PlayChar);
}
else{

View File

@ -5,7 +5,7 @@
#include <WString.h>//F()
#include "bands.h"
#include "button.h"
#include "button_grid.h"
#include "color_theme.h"
#include "menu_main.h"
#include "menu_numpad.h"
@ -54,10 +54,6 @@ void toVfoA(char* text_out, const uint16_t max_text_size);
ButtonStatus_e bsVfoA();
void osVfoA();
constexpr Button bVfoA PROGMEM = {
LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X,
LAYOUT_VFO_LABEL_Y,
LAYOUT_VFO_LABEL_WIDTH,
LAYOUT_VFO_LABEL_HEIGHT,
nullptr,
toVfoA,
bsVfoA,
@ -69,10 +65,6 @@ void toVfoB(char* text_out, const uint16_t max_text_size);
ButtonStatus_e bsVfoB();
void osVfoB();
constexpr Button bVfoB PROGMEM = {
LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X,
LAYOUT_VFO_LABEL_Y,
LAYOUT_VFO_LABEL_WIDTH,
LAYOUT_VFO_LABEL_HEIGHT,
nullptr,
toVfoB,
bsVfoB,
@ -84,10 +76,6 @@ constexpr char txtRit [] PROGMEM = "RIT";
ButtonStatus_e bsRit();
void osRit();
constexpr Button bRit PROGMEM = {
LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txtRit,
nullptr,
bsRit,
@ -99,10 +87,6 @@ constexpr char txtUsb [] PROGMEM = "USB";
ButtonStatus_e bsUsb();
void osUsb();
constexpr Button bUsb PROGMEM = {
LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txtUsb,
nullptr,
bsUsb,
@ -114,10 +98,6 @@ constexpr char txtLsb [] PROGMEM = "LSB";
ButtonStatus_e bsLsb();
void osLsb();
constexpr Button bLsb PROGMEM = {
LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txtLsb,
nullptr,
bsLsb,
@ -129,10 +109,6 @@ constexpr char txtCw [] PROGMEM = "CW";
ButtonStatus_e bsCw();
void osCw();
constexpr Button bCw PROGMEM = {
LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txtCw,
nullptr,
bsCw,
@ -144,10 +120,6 @@ constexpr char txtSpl [] PROGMEM = "SPL";
ButtonStatus_e bsSpl();
void osSpl();
constexpr Button bSpl PROGMEM = {
LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txtSpl,
nullptr,
bsSpl,
@ -159,10 +131,6 @@ constexpr char txt80 [] PROGMEM = "80";
ButtonStatus_e bs80();
void os80();
constexpr Button b80 PROGMEM = {
LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txt80,
nullptr,
bs80,
@ -174,10 +142,6 @@ constexpr char txt40 [] PROGMEM = "40";
ButtonStatus_e bs40();
void os40();
constexpr Button b40 PROGMEM = {
LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txt40,
nullptr,
bs40,
@ -189,10 +153,6 @@ constexpr char txt30 [] PROGMEM = "30";
ButtonStatus_e bs30();
void os30();
constexpr Button b30 PROGMEM = {
LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txt30,
nullptr,
bs30,
@ -204,10 +164,6 @@ constexpr char txt20 [] PROGMEM = "20";
ButtonStatus_e bs20();
void os20();
constexpr Button b20 PROGMEM = {
LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txt20,
nullptr,
bs20,
@ -219,10 +175,6 @@ constexpr char txt17 [] PROGMEM = "17";
ButtonStatus_e bs17();
void os17();
constexpr Button b17 PROGMEM = {
LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txt17,
nullptr,
bs17,
@ -234,10 +186,6 @@ constexpr char txt15 [] PROGMEM = "15";
ButtonStatus_e bs15();
void os15();
constexpr Button b15 PROGMEM = {
LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txt15,
nullptr,
bs15,
@ -249,10 +197,6 @@ constexpr char txt10 [] PROGMEM = "10";
ButtonStatus_e bs10();
void os10();
constexpr Button b10 PROGMEM = {
LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txt10,
nullptr,
bs10,
@ -264,10 +208,6 @@ constexpr char txtMenu [] PROGMEM = "\x7F";//gear icon
ButtonStatus_e bsIgnore();
void osMenu();
constexpr Button bMenu PROGMEM = {
LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txtMenu,
nullptr,
bsIgnore,
@ -279,10 +219,6 @@ constexpr char txtNumpad [] PROGMEM = "FRQ";
ButtonStatus_e bsIgnore();
void osNumpad();
constexpr Button bNumpad PROGMEM = {
LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txtNumpad,
nullptr,
bsIgnore,
@ -290,15 +226,39 @@ constexpr Button bNumpad PROGMEM = {
'F'
};
const Button* const mainMenuButtons [] PROGMEM = {
&bVfoA, &bVfoB,
&bRit, &bUsb, &bLsb, &bCw, &bSpl,
&b80, &b40, &b30, &b20, &b17,
&b15, &b10, &bMenu, &bNumpad
const Button* const mainMenuVfoButtons [] PROGMEM = {
&bVfoA, &bVfoB
};
const uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]);
const ButtonGrid_t mainMenuVfoGrid PROGMEM = {
LAYOUT_VFO_LABEL_X,
LAYOUT_VFO_LABEL_Y,
LAYOUT_VFO_LABEL_WIDTH,
LAYOUT_VFO_LABEL_HEIGHT,
LAYOUT_VFO_LABEL_PITCH_X,
0,//not used, since it's just one row
1,//rows
2,//cols
mainMenuVfoButtons
};
const Button* const mainMenuButtons [] PROGMEM = {
&bRit, &bUsb, &bLsb, &bCw, &bSpl,
&b80, &b40, &b30, &b20, &b17,
&b15, &b10, nullptr, &bMenu, &bNumpad
};
const ButtonGrid_t mainMenuGrid PROGMEM = {
LAYOUT_BUTTON_X,
LAYOUT_BUTTON_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_PITCH_Y,
3,//rows
5,//cols
mainMenuButtons
};
void updateBandButtons(const uint32_t old_freq)
{
@ -310,7 +270,7 @@ void updateBandButtons(const uint32_t old_freq)
for(uint8_t i = 0; i < sizeof(bands)/sizeof(bands[0]); ++i){
if(isFreqInBand(old_freq,bands[i]) != isFreqInBand(curr_freq,bands[i])){
memcpy_P(&button,band_buttons[i],sizeof(button));
drawButton(&button);
drawButton(&mainMenuGrid,band_buttons[i]);
morseBool(ButtonStatus_e::Active == button.status());
}
}
@ -374,11 +334,8 @@ void osVfo(const Vfo_e vfo){
ltoa(GetActiveVfoFreq(),b,10);
morseText(b);
Button button;
memcpy_P(&button,&bVfoA,sizeof(button));
drawButton(&button);
memcpy_P(&button,&bVfoB,sizeof(button));
drawButton(&button);
drawButton(&mainMenuGrid,&bVfoA);
drawButton(&mainMenuGrid,&bVfoB);
updateBandButtons(old_freq);
}
@ -406,7 +363,6 @@ ButtonStatus_e bsRit(){
return globalSettings.ritOn ? ButtonStatus_e::Active : ButtonStatus_e::Inactive;
}
void osRit(){
Button button;
if(!globalSettings.ritOn){
globalSettings.ritOn = true;
globalSettings.ritFrequency = GetActiveVfoFreq();
@ -426,17 +382,14 @@ void osRit(){
displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND);
if(Vfo_e::VFO_A == globalSettings.activeVfo){
memcpy_P(&button,&bVfoA,sizeof(button));
drawButton(&button);
drawButton(&mainMenuVfoGrid,&bVfoA);
}
else{
memcpy_P(&button,&bVfoB,sizeof(button));
drawButton(&button);
drawButton(&mainMenuVfoGrid,&bVfoB);
}
}
memcpy_P(&button,&bRit,sizeof(button));
drawButton(&button);
drawButton(&mainMenuGrid,&bRit);
}
void osSidebandMode(VfoMode_e mode){
@ -444,11 +397,8 @@ void osSidebandMode(VfoMode_e mode){
setFrequency(GetActiveVfoFreq());
SaveSettingsToEeprom();
Button button;
memcpy_P(&button,&bUsb,sizeof(button));
drawButton(&button);
memcpy_P(&button,&bLsb,sizeof(button));
drawButton(&button);
drawButton(&mainMenuGrid,&bUsb);
drawButton(&mainMenuGrid,&bLsb);
}
void updateSidebandButtons()
@ -486,9 +436,7 @@ void osCw(){
setFrequency(GetActiveVfoFreq());
Button button;
memcpy_P(&button,&bCw,sizeof(button));
drawButton(&button);
drawButton(&mainMenuGrid,&bCw);
}
ButtonStatus_e bsSpl(){
@ -498,13 +446,9 @@ ButtonStatus_e bsSpl(){
void osSpl(){
globalSettings.splitOn = !globalSettings.splitOn;
Button button;
memcpy_P(&button,&bSpl,sizeof(button));
drawButton(&button);
memcpy_P(&button,&bVfoA,sizeof(button));
drawButton(&button);
memcpy_P(&button,&bVfoB,sizeof(button));
drawButton(&button);
drawButton(&mainMenuGrid,&bSpl);
drawButton(&mainMenuVfoGrid,&bVfoA);
drawButton(&mainMenuVfoGrid,&bVfoB);
}
ButtonStatus_e bsBand(const uint8_t band){
@ -518,14 +462,11 @@ void osBand(const uint8_t band){
updateSidebandButtons();
}
Button button;
if(Vfo_e::VFO_A == globalSettings.activeVfo){
memcpy_P(&button,&bVfoA,sizeof(button));
drawButton(&button);
drawButton(&mainMenuVfoGrid,&bVfoA);
}
else if(Vfo_e::VFO_B == globalSettings.activeVfo){
memcpy_P(&button,&bVfoB,sizeof(button));
drawButton(&button);
drawButton(&mainMenuVfoGrid,&bVfoB);
}
updateBandButtons(old_freq);

View File

@ -2,12 +2,12 @@
#include <stdint.h>
#include "button.h"
extern const Button* const mainMenuButtons[];
extern const uint8_t MAIN_MENU_NUM_BUTTONS;
#include "button_grid.h"
extern const ButtonGrid_t mainMenuVfoGrid;
extern const ButtonGrid_t mainMenuGrid;
extern const Button bVfoA;
extern const Button bVfoB;
void updateBandButtons(const uint32_t old_freq);
void updateSidebandButtons();

View File

@ -25,13 +25,7 @@ int16_t numpadMenuSelectedItemRaw = 0;//Allow negative only for easier checks on
void drawNumpad(void)
{
displayFillrect(0,47,320,200,COLOR_BACKGROUND);
Button button;
Button* bp;
for(uint8_t i = 0; i < NUMPAD_MENU_NUM_BUTTONS; ++i){
memcpy_P(&bp, &(numpadMenuButtons[i]), sizeof(bp));
memcpy_P(&button,bp,sizeof(button));
drawButton(&button);
}
drawButtonGrid(&numpadMenuGrid);
}
void initNumpad(void)
@ -39,8 +33,7 @@ void initNumpad(void)
numpadMenuFrequency = 0;
drawNumpad();
initSelector(&numpadMenuSelectedItemRaw,
numpadMenuButtons,
NUMPAD_MENU_NUM_BUTTONS,
&numpadMenuGrid,
MorsePlaybackType_e::PlayChar);
}
@ -51,18 +44,25 @@ MenuReturn_e runNumpad(const ButtonPress_e tuner_button,
{
if(ButtonPress_e::NotPressed != tuner_button){
//We treat long and short presses the same, so no need to have a switch
ButtonGrid_t button_grid;
memcpy_P(&button_grid,&numpadMenuGrid,sizeof(button_grid));
uint8_t menu_index = numpadMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM;
Button button;
Button* bp;
memcpy_P(&bp,&(numpadMenuButtons[menu_index]),sizeof(bp));
memcpy_P(&button,bp,sizeof(button));
button.on_select();
memcpy_P(&bp,&(button_grid.buttons_P[menu_index]),sizeof(bp));
if(nullptr != bp){
Button button;
memcpy_P(&button,bp,sizeof(button));
button.on_select();
}
}//tuner_button
else if(ButtonPress_e::NotPressed != touch_button){
//We treat long and short presses the same, so no need to have a switch
Button button;
if(findPressedButton(numpadMenuButtons,NUMPAD_MENU_NUM_BUTTONS,&button,touch_point)){
if(findPressedButton(&numpadMenuGrid,&button,touch_point)){
button.on_select();
}
else{
@ -73,8 +73,7 @@ MenuReturn_e runNumpad(const ButtonPress_e tuner_button,
else{//Neither button input type found, so handle the knob
adjustSelector(&numpadMenuSelectedItemRaw,
knob,
numpadMenuButtons,
NUMPAD_MENU_NUM_BUTTONS,
&numpadMenuGrid,
MorsePlaybackType_e::PlayChar);
}

View File

@ -27,15 +27,11 @@ uint32_t numpadMenuFrequency;
#define D_STRINGIFY(x) #x
#define D_STRING(x) D_STRINGIFY(x)
#define NUMBER_BUTTON_GENERATE(number,x,y) \
#define NUMBER_BUTTON_GENERATE(number) \
constexpr char txt##number [] PROGMEM = "" D_STRING(number);\
ButtonStatus_e bs##number();\
void os##number();\
constexpr Button b##number PROGMEM = {\
LAYOUT_BUTTON_X + x*LAYOUT_BUTTON_PITCH_X,\
LAYOUT_BUTTON_Y + y*LAYOUT_BUTTON_PITCH_Y,\
LAYOUT_BUTTON_WIDTH,\
LAYOUT_BUTTON_HEIGHT,\
txt##number,\
nullptr,\
bsNumpad,\
@ -47,28 +43,20 @@ ButtonStatus_e bsNumpad(void){
return ButtonStatus_e::Stateless;
}
// 1 2 3 Ok
// 4 5 6 0 <-
// 7 8 9 Can
NUMBER_BUTTON_GENERATE(1,0,0);
NUMBER_BUTTON_GENERATE(2,1,0);
NUMBER_BUTTON_GENERATE(3,2,0);
NUMBER_BUTTON_GENERATE(4,0,1);
NUMBER_BUTTON_GENERATE(5,1,1);
NUMBER_BUTTON_GENERATE(6,2,1);
NUMBER_BUTTON_GENERATE(7,0,2);
NUMBER_BUTTON_GENERATE(8,1,2);
NUMBER_BUTTON_GENERATE(9,2,2);
NUMBER_BUTTON_GENERATE(0,3,1);
NUMBER_BUTTON_GENERATE(1);
NUMBER_BUTTON_GENERATE(2);
NUMBER_BUTTON_GENERATE(3);
NUMBER_BUTTON_GENERATE(4);
NUMBER_BUTTON_GENERATE(5);
NUMBER_BUTTON_GENERATE(6);
NUMBER_BUTTON_GENERATE(7);
NUMBER_BUTTON_GENERATE(8);
NUMBER_BUTTON_GENERATE(9);
NUMBER_BUTTON_GENERATE(0);
constexpr char txtOk [] PROGMEM = "OK";
void osOk();
constexpr Button bOk PROGMEM = {
LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txtOk,
nullptr,
bsNumpad,
@ -79,10 +67,6 @@ constexpr Button bOk PROGMEM = {
constexpr char txtBackspace [] PROGMEM = "<-";
void osBackspace();
constexpr Button bBackspace PROGMEM = {
LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txtBackspace,
nullptr,
bsNumpad,
@ -93,10 +77,6 @@ constexpr Button bBackspace PROGMEM = {
constexpr char txtCancel [] PROGMEM = "Can";
void osCancel();
constexpr Button bCancel PROGMEM = {
LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
txtCancel,
nullptr,
bsNumpad,
@ -106,10 +86,22 @@ constexpr Button bCancel PROGMEM = {
//Declare in menu select order, not graphical order
const Button* const numpadMenuButtons [] PROGMEM = {
&b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &b9, &b0,
&bOk, &bBackspace, &bCancel
&b1, &b2, &b3, nullptr, &bOk,
&b4, &b5, &b6, &b0, &bBackspace,
&b7, &b8, &b9, nullptr, &bCancel
};
const ButtonGrid_t numpadMenuGrid PROGMEM = {
LAYOUT_BUTTON_X,
LAYOUT_BUTTON_Y,
LAYOUT_BUTTON_WIDTH,
LAYOUT_BUTTON_HEIGHT,
LAYOUT_BUTTON_PITCH_X,
LAYOUT_BUTTON_PITCH_Y,
3,//rows
5,//cols
numpadMenuButtons
};
const uint8_t NUMPAD_MENU_NUM_BUTTONS = sizeof(numpadMenuButtons)/sizeof(numpadMenuButtons[0]);
void updateCurrentEnteredFrequency(void)
{

View File

@ -2,10 +2,9 @@
#include <stdint.h>
#include "button.h"
#include "button_grid.h"
extern const Button* const numpadMenuButtons[];
extern const uint8_t NUMPAD_MENU_NUM_BUTTONS;
extern const ButtonGrid_t numpadMenuGrid;
extern const uint32_t NUMPAD_MENU_EXIT_FREQ;
extern uint32_t numpadMenuFrequency;

View File

@ -2,40 +2,80 @@
#include <avr/pgmspace.h>
#include "button.h"
#include "button_grid.h"
#include "color_theme.h"
#include "morse.h"
#include "nano_gui.h"
#include "utils.h"
bool findPressedButton(const Button* const* buttons,
const uint8_t num_buttons,
bool findPressedButton(const ButtonGrid_t *const button_grid_P,
Button *const button_out,
const Point touch_point)
{
Button* bp;
for(uint16_t i = 0; i < num_buttons; ++i){
memcpy_P(&bp,&(buttons[i]),sizeof(bp));
memcpy_P(button_out,bp,sizeof(*button_out));
if((button_out->x <= touch_point.x)
&&(touch_point.x <= button_out->x + button_out->w)
&&(button_out->y <= touch_point.y)
&&(touch_point.y <= button_out->y + button_out->h)){
return true;
}
ButtonGrid_t button_grid;
memcpy_P(&button_grid,button_grid_P,sizeof(button_grid));
if((touch_point.x < button_grid.top_left_x)
||(touch_point.y < button_grid.top_left_y)
||(touch_point.x > (int16_t)button_grid.button_pitch_x * button_grid.num_button_cols)
||(touch_point.y > (int16_t)button_grid.button_pitch_y * button_grid.num_button_rows)){
//touch point was outside the button grid
return false;
}
uint8_t row = (touch_point.x - button_grid.top_left_x) / button_grid.button_pitch_x;
uint8_t col = (touch_point.y - button_grid.top_left_y) / button_grid.button_pitch_y;
int16_t x_max = (col * button_grid.button_pitch_x) + button_grid.button_width;
int16_t y_max = (row * button_grid.button_pitch_y) + button_grid.button_height;
if((touch_point.x > x_max)
||(touch_point.y > y_max)){
//touch point was outside of the button
return false;
}
return false;
Button* bp;
memcpy_P(&bp,&(button_grid.buttons_P[row * button_grid.num_button_cols + col]),sizeof(bp));
if(nullptr == bp){
//no button there
return false;
}
memcpy_P(button_out,bp,sizeof(*button_out));
return true;
}
void movePuck(const Button *const b_old,
const Button *const b_new)
void indexToRowCol(const ButtonGrid_t *const button_grid,
const int8_t index,
uint8_t *const row_out,
uint8_t *const col_out)
{
if(nullptr != b_old){
displayRect(b_old->x,b_old->y,b_old->w,b_old->h,COLOR_INACTIVE_BORDER);
*row_out = index / button_grid->num_button_cols;
*col_out = index % button_grid->num_button_cols;
}
void movePuck(const ButtonGrid_t *const button_grid,
const int8_t old_index,
const int8_t new_index)
{
if(-1 != old_index){
uint8_t row;
uint8_t col;
indexToRowCol(button_grid,old_index,&row,&col);
displayRect(button_grid->top_left_x + button_grid->button_pitch_x * col,
button_grid->top_left_y + button_grid->button_pitch_y * row,
button_grid->button_width,
button_grid->button_height,
COLOR_INACTIVE_BORDER);
}
if(nullptr != b_new){
displayRect(b_new->x,b_new->y,b_new->w,b_new->h,COLOR_ACTIVE_BORDER);
if(-1 != new_index){
uint8_t row;
uint8_t col;
indexToRowCol(button_grid,new_index,&row,&col);
displayRect(button_grid->top_left_x + button_grid->button_pitch_x * col,
button_grid->top_left_y + button_grid->button_pitch_y * row,
button_grid->button_width,
button_grid->button_height,
COLOR_ACTIVE_BORDER);
}
}
@ -59,45 +99,72 @@ void playButtonMorse(const Button *const button,
}
void initSelector(int16_t *const raw_select_val_in_out,
const Button* const* buttons,
const uint8_t num_buttons,
const ButtonGrid_t *const button_grid_P,
const MorsePlaybackType_e play_type)
{
ButtonGrid_t button_grid;
memcpy_P(&button_grid,button_grid_P,sizeof(button_grid));
*raw_select_val_in_out = 0;
if(0 < num_buttons){
if(0 < button_grid.num_button_rows * button_grid.num_button_cols){
Button button;
Button* bp;
memcpy_P(&bp,&(buttons[0]),sizeof(bp));
memcpy_P(&bp,&(button_grid.buttons_P[0]),sizeof(bp));
memcpy_P(&button,bp,sizeof(button));
movePuck(nullptr,&button);
movePuck(&button_grid,-1,0);
playButtonMorse(&button,play_type);
}
}
void adjustSelector(int16_t *const raw_select_val_in_out,
const int16_t knob,
const Button* const* buttons,
const uint8_t num_buttons,
int16_t knob,
const ButtonGrid_t *const button_grid_P,
const MorsePlaybackType_e play_type)
{
const uint8_t prev_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM;
*raw_select_val_in_out = LIMIT((*raw_select_val_in_out)+knob,0,num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1);
const uint8_t new_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM;
if(prev_select != new_select){
Button prev_button;
Button* bp;
memcpy_P(&bp,&(buttons[prev_select]),sizeof(bp));
memcpy_P(&prev_button,bp,sizeof(prev_button));
Button new_button;
memcpy_P(&bp,&(buttons[new_select]),sizeof(bp));
memcpy_P(&new_button,bp,sizeof(new_button));
ButtonGrid_t button_grid;
memcpy_P(&button_grid,button_grid_P,sizeof(button_grid));
movePuck(&prev_button,&new_button);
playButtonMorse(&new_button,play_type);
const uint8_t num_buttons = button_grid.num_button_rows * button_grid.num_button_cols;
const uint8_t prev_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM;
*raw_select_val_in_out += knob;
bool keep_trying = true;
while(keep_trying){
*raw_select_val_in_out = LIMIT(*raw_select_val_in_out,0,num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1);
const uint8_t new_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM;
if(prev_select != new_select){
Button* bp;
memcpy_P(&bp,&(button_grid.buttons_P[new_select]),sizeof(bp));
if(nullptr == bp){
if(new_select > prev_select){
*raw_select_val_in_out += MENU_KNOB_COUNTS_PER_ITEM;
}
else{
*raw_select_val_in_out -= MENU_KNOB_COUNTS_PER_ITEM;
}
if((*raw_select_val_in_out <= 0)
||(*raw_select_val_in_out >= num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1)){
keep_trying = false;
}
continue;
}
Button new_button;
memcpy_P(&new_button,bp,sizeof(new_button));
movePuck(&button_grid,prev_select,new_select);
playButtonMorse(&new_button,play_type);
}
}
}
void endSelector(const Button *const button)
void endSelector(const int16_t raw_select,
const ButtonGrid_t *const button_grid_P)
{
movePuck(button,nullptr);
ButtonGrid_t button_grid;
memcpy_P(&button_grid,button_grid_P,sizeof(button_grid));
uint8_t index = raw_select/MENU_KNOB_COUNTS_PER_ITEM;
movePuck(&button_grid,index,-1);
}

View File

@ -1,11 +1,10 @@
#pragma once
#include "button.h"
#include "button_grid.h"
#include "menu.h"
//Returns true if button was found, false otherwise
bool findPressedButton(const Button* const* buttons,
const uint8_t num_buttons,
bool findPressedButton(const ButtonGrid_t *const button_grid_P,
Button *const button_out,
const Point touch_point);
@ -14,14 +13,13 @@ enum MorsePlaybackType_e : uint8_t {
PlayText
};
void initSelector(int16_t *const raw_select_val_in_out,
const Button* const* buttons,
const uint8_t num_buttons,
const MorsePlaybackType_e);
const ButtonGrid_t *const button_grid_P,
const MorsePlaybackType_e play_type);
void adjustSelector(int16_t *const raw_select_val_in_out,
int16_t knob,
const Button* const* buttons,
const uint8_t num_buttons,
const MorsePlaybackType_e);
const ButtonGrid_t *const button_grid_P,
const MorsePlaybackType_e play_type);
void endSelector(const Button *const button);
void endSelector(const int16_t raw_select,
const ButtonGrid_t *const button_grid_P);