From b73124349956eff879bcff1ad2cd71594125d973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zombori=20D=C3=A1niel?= Date: Mon, 4 May 2020 00:01:21 +0200 Subject: [PATCH] Release v0.1.0 --- LICENSE | 2 +- README.md | 13 +++ library.json | 21 ++++ media/menu1.jpg | Bin 0 -> 27379 bytes media/menu2.jpg | Bin 0 -> 27375 bytes media/menu3.jpg | Bin 0 -> 27675 bytes media/menu4.jpg | Bin 0 -> 27601 bytes src/font.c | 119 ++++++++++++++++++++++ src/font.h | 19 ++++ src/hx1230.c | 174 +++++++++++++++++++++++++++++++ src/hx1230.h | 47 +++++++++ src/hx1230_menu.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++ src/hx1230_menu.h | 85 ++++++++++++++++ 13 files changed, 733 insertions(+), 1 deletion(-) create mode 100644 library.json create mode 100644 media/menu1.jpg create mode 100644 media/menu2.jpg create mode 100644 media/menu3.jpg create mode 100644 media/menu4.jpg create mode 100644 src/font.c create mode 100644 src/font.h create mode 100644 src/hx1230.c create mode 100644 src/hx1230.h create mode 100644 src/hx1230_menu.c create mode 100644 src/hx1230_menu.h diff --git a/LICENSE b/LICENSE index 2c5e3e5..b1fbcf8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2020, RockerM4NHUN +Copyright (c) 2020, ZOMBORI Dániel All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.md b/README.md index 40bd5bb..f8b22d4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,15 @@ # HX1230Menu Menu system for HX1230 96x68 LCD screen in PlatformIO STM32 environment. + +# Menu items +- Titles +- Submenus (menu tree) +- Toggle switches (binary variable, value is shown by graphics) +- Push buttons (function call) +- Sliders (int16 value with limits and step size) +- Custom mode (execution loop activated through menu) + +![](media/menu1.jpg) +![](media/menu2.jpg) +![](media/menu3.jpg) +![](media/menu4.jpg) diff --git a/library.json b/library.json new file mode 100644 index 0000000..eae3880 --- /dev/null +++ b/library.json @@ -0,0 +1,21 @@ +{ + "name": "HX1230Menu", + "keywords": "stm32, stm32cube, hx1230, menu system", + "description": "Menu system for HX1230 96x68 LCD screen in PlatformIO STM32 environment.", + "license": "BSD-3-Clause", + "repository": + { + "type": "git", + "url": "https://github.com/RockerM4NHUN/HX1230Menu.git" + }, + "authors": + { + "name": "ZOMBORI Dániel", + "email": "rockerm4nhun@gmail.com", + "url": "https://github.com/RockerM4NHUN", + "maintainer": true + }, + "version": "0.1.0", + "frameworks": "stm32cube", + "platforms": "stm32, ststm32" +} diff --git a/media/menu1.jpg b/media/menu1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0e35b21b14bc17877dcffd140ea1c0c4ef0b6891 GIT binary patch literal 27379 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�rQ0XU_$yT}-OKvOl_Vuj} z{t!2$)eM{_NZ}+J&4K)Yfo7GX*7x`bSH#OJ!?n|2ST?L{f`4DbKWkmV(0T5vwRNP9 zqR%4pZmIT5k}l<`{uDD7rSkeC{#qV6D)wmZ_uCy(U6r3%f~{ak1lOAZ;H3z4^c!nw zJS{JMA#Cdk{4_GZgxYyGnQ!m8%Zz$cyjtI<<4XS!Q%ceYx949U$|GBlk2lwXv`$`^ zmrx+p)JsUe8%h@^SvuLt=lKL#sfW4YTrdh=^6n$Fd`fRtanfdZvGC=kU}IXBiO+k% zyjB*%ZGnza8mm-2uuX|^aN&r66p1(M_RXu^81`WAc;dqLoNifF#^jtzO{VkH?DexG z34>>V6F5;3CjqDF_E^30T+-UT84UE$;w|Ch*^A!)M*v^}pZ>df_2_&*q4=&nXlfHI zm$B-%J1xb#ALMe=~>hC;SwqF9LWI;xu>O57B%>;-3&(!6aI)rKek5t*k^^#3AyXOmDXnFliCS z=8xqYPVXQ1k^6sm*Wz!9yf<-tz8#PL5&Ow5V2;DXdVZG~e%V`CqaQ9?2dLb6g{*;pD~W9H(FP3e&;9qUH;VGB>k>_K59NR@kP^3e|a1*#(_rL zOL${ciWvPB5kim0)aS}0yGZAdtZn5nI9>k$Fde>Ze@=a> zBh9{U>U2(Z&tSh}r-5_oDrzbK9v&W0 z3jP7unJc==-gfr^KvNUo0|0;oAjhKw@Ii_l#27rPpEMCj7vr7#NuLAhN<12X01WZK zKLC#jIP;SRfOb6Qzvypxyub5+((puomc0Px`;LG9U;JP@fbe(O^_N_KXyyk1!0gZd zKLS2hC=90;u3f)EQDISGSz!rTVKH`5F~YaDyfDPhB|rcU>R} zWd5$}Cr$X5%)6OHzvbZa2>)z9u2+FoR)7=?a5M!j4g!v5`;BD(S&#o`JTU*SF$@4H zAk7Y<&F>Hley077pX&yr%Mh>{0zec@0(%{#2!5Jn52Oh}`Vz=TgESG?(DNXD6|@sE zNYjC|K1h>*xp2)4y>uQp3(_lK-S!~=+;2VrTp+|v3{V6>NeciBxZL1B9Y`~Rd|X)^ zvizn&5?}>s+;pS^D`ER12doAH@|8ipB*?!6(%(S30i-#=Jh-WS7wlEsK<5PM2O!N0 zO2*0g1kwV3S zUmPk>CLTa^64e;(~G9Caf7XKGe(^QrHYeiyLzpbnaU{&ng9K9^vY}gHL z+}!P)o!CVLg@u7kDzM+dvg9D*tcA1WGKl%V<2aphyw{+@oM4F48yCl6B^X)%&BIv^ z#{=gT&<+wfS-3Xhcn`tV0XG71Wq&SWVAuf8oGW06laK2eT)uUXCl7|We7FgQF&Zh-Os zA>fq$gJ2)x`sGiVb+Bwcs5l1f=nr5Tj<)_E3i{tqz%>tN%iCasadu?}>%sL4j{g`$ z9Q>J(|E|hgFhAHV02gM1SPNo5h)W>;R|GY1ezb%0Ap*BlQUkyXkp8a-AHc!-9Mr`d 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 literal 0 HcmV?d00001 diff --git a/media/menu3.jpg b/media/menu3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0645a224e59563695f29cf49dddcaa24930daccf GIT binary patch literal 27675 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

6hY1JDAK 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",30*/ +0x04,0x52,0x0A,0x04, /*"?",31*/ +0x3C,0x42,0x5A,0x56,0x5C, /*"@",32*/ +0x7C,0x12,0x12,0x7C, /*"A",33*/ +0x7E,0x4A,0x4A,0x34, /*"B",34*/ +0x3C,0x42,0x42,0x24, /*"C",35*/ +0x7E,0x42,0x42,0x3C, /*"D",36*/ +0x7E,0x4A,0x4A,0x42, /*"E",37*/ +0x7E,0x0A,0x0A,0x02, /*"F",38*/ +0x3C,0x42,0x52,0x34, /*"G",39*/ +0x7E,0x08,0x08,0x7E, /*"H",40*/ +0x42,0x7E,0x42,0x00, /*"I",41*/ +0x20,0x40,0x40,0x3E, /*"J",42*/ +0x7E,0x08,0x14,0x62, /*"K",43*/ +0x7E,0x40,0x40,0x40, /*"L",44*/ +0x7E,0x04,0x08,0x04,0x7E, /*"M",45*/ +0x7E,0x08,0x10,0x7E, /*"N",46*/ +0x3C,0x42,0x42,0x3C, /*"O",47*/ +0x7E,0x12,0x12,0x0C, /*"P",48*/ +0x3C,0x42,0x62,0xBC, /*"Q",49*/ +0x7E,0x12,0x12,0x6C, /*"R",50*/ +0x24,0x4A,0x52,0x24, /*"S",51*/ +0x02,0x02,0x7E,0x02,0x02, /*"T",52*/ +0x3E,0x40,0x40,0x3E, /*"U",53*/ +0x1E,0x20,0x40,0x20,0x1E, /*"V",54*/ +0x3E,0x40,0x38,0x40,0x3E, /*"W",55*/ +0x66,0x18,0x18,0x66, /*"X",56*/ +0x06,0x08,0x70,0x08,0x06, /*"Y",57*/ +0x62,0x52,0x4A,0x46, /*"Z",58*/ + +0x00 +}; + +const int8_t offsets[] = { + 0, 0, + 1,-1, + 2,-2, + 4,-1, + 5, 0, + 6, 1, + 7, 2, + 9, 1, +10, 0, +11, 1, +12, 2, +13, 1, +15, 0, +18,-1, +27,-2, +28,-3, +33,-2, +46,-1, +53, 0, +55, 1, +56, 2, +58, 3, +127,-128 +}; + +int8_t getOffset(uint8_t code){ + uint8_t i = 0; + while(offsets[i] <= code){ + i += 2; + } + i -= 2; + return offsets[i+1]; +} + +/* if data is NULL only the length will be returned */ +/* otherwise data is handled as a pointers mem address*/ +/* returns the number of bytes length */ +uint8_t getCharData(char ascii, const uint8_t** data){ + if (ascii >= 'a' && ascii <= 'z'){ + ascii = ascii - 'a' + 'A'; + } else if (ascii > 'Z' || ascii < ' '){ + ascii = '?'; + } + uint8_t code = ascii-' '; // normalize to charset code + uint8_t offset = getOffset(code) + code * 4; // get offset in charset + uint8_t length = getOffset(code+1) + (code + 1) * 4 - offset; + if (data != 0){ + *data = charset+offset; + } + return length; +} diff --git a/src/font.h b/src/font.h new file mode 100644 index 0000000..44bbb81 --- /dev/null +++ b/src/font.h @@ -0,0 +1,19 @@ + +#ifndef _FONT_H_ +#define _FONT_H_ + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +uint8_t getCharData(char, const uint8_t**); +extern const uint8_t charset[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _FONT_H_ */ + diff --git a/src/hx1230.c b/src/hx1230.c new file mode 100644 index 0000000..66ce3ee --- /dev/null +++ b/src/hx1230.c @@ -0,0 +1,174 @@ +#include "hx1230.h" +#include "font.h" + +#define SPI_TIMEOUT 10 + +static SPI_HandleTypeDef* _hspi; + +static void WriteSingle(uint16_t data){ + HAL_GPIO_WritePin(HX1230_nCE_GPIO_Port,HX1230_nCE_Pin,GPIO_PIN_RESET); + + HAL_SPI_Transmit(_hspi,(uint8_t*)&data,1,SPI_TIMEOUT); + + HAL_GPIO_WritePin(HX1230_nCE_GPIO_Port,HX1230_nCE_Pin,GPIO_PIN_SET); +} + +void HX1230_Stream(const uint16_t* data, uint16_t length){ + HAL_GPIO_WritePin(HX1230_nCE_GPIO_Port,HX1230_nCE_Pin,GPIO_PIN_RESET); + + // WARNING: why is length staying the same? Maybe SPI implementation works like this. + // -> it is deliberatly converted "badly" + HAL_SPI_Transmit(_hspi,(uint8_t*)data,length,SPI_TIMEOUT); + + HAL_GPIO_WritePin(HX1230_nCE_GPIO_Port,HX1230_nCE_Pin,GPIO_PIN_SET); +} + + +void HX1230_Init(SPI_HandleTypeDef * hspi){ + _hspi = hspi; + + HAL_GPIO_WritePin(HX1230_nRST_GPIO_Port,HX1230_nRST_Pin,GPIO_PIN_RESET); + HAL_GPIO_WritePin(HX1230_nCE_GPIO_Port,HX1230_nCE_Pin,GPIO_PIN_RESET); + + HAL_Delay(50); + + HAL_GPIO_WritePin(HX1230_nRST_GPIO_Port,HX1230_nRST_Pin,GPIO_PIN_SET); + + HAL_Delay(1); + + HAL_GPIO_WritePin(HX1230_nCE_GPIO_Port,HX1230_nCE_Pin,GPIO_PIN_SET); + + WriteSingle(HX1230_TURN_ON); + WriteSingle(HX1230_INVERT_OFF); + WriteSingle(HX1230_PIXEL_TEST_OFF); + WriteSingle(HX1230_DISPLAY_ON); + HX1230_Scan_Offset(0); + HX1230_SetXY(0,0); +} + +void HX1230_Command(uint8_t cmd){ + WriteSingle(cmd); +} + +void HX1230_Clear(){ + uint16_t words[8] = {0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100}; + HX1230_SetXY(0,0); + for (int i = 0; i < HX1230_ROWS * 12; i++){ + HX1230_Stream(words, 8); + } + HX1230_SetXY(0,0); +} + +void HX1230_PixelTest(){ + WriteSingle(HX1230_PIXEL_TEST_ON); + HAL_Delay(1000); + WriteSingle(HX1230_PIXEL_TEST_OFF); +} + +void HX1230_SetXY(uint8_t x, uint8_t y){ + + if (x > 95){ + x -= 96; + } + + WriteSingle(0xB0 | (y & 0x07)); + WriteSingle(0x10 | ((x >> 4) & 0x07)); + WriteSingle(x & 0x0F); +} + +void HX1230_SetX(uint8_t x){ + + if (x > 95){ + x -= 96; + } + + WriteSingle(0x10 | ((x >> 4) & 0x07)); + WriteSingle(x & 0x0F); +} + +void HX1230_SetY(uint8_t y){ + WriteSingle(0xB0 | (y & 0x07)); +} + +void HX1230_Scan_Offset(uint8_t y){ + WriteSingle(0x40 | (y & 0x3F)); +} + +void HX1230_Draw(const uint8_t* data, uint16_t length){ + uint16_t words[length]; + for(int i = 0; i < length; i++){ + words[i] = 0x100 | data[i]; + } + + HX1230_Stream(words, length); +} + +/* Implementation only handles breaking between characters. */ +uint16_t HX1230_Print(uint8_t x, uint8_t y, const char* text, uint16_t length){ + HX1230_SetXY(x,y); + const uint8_t* pdata; + + uint8_t row = y; + uint8_t col = x; + uint16_t slices = 0; + + for(uint16_t chari = 0; chari < length; chari++){ + uint8_t width = getCharData(text[chari],&pdata); + if (col + width > HX1230_COLS){ + // Not fits in row + row++; + col = 0; + + if (row > HX1230_ROWS) return slices; + + HX1230_SetXY(0,row); + slices = row * HX1230_COLS; + + // If last character is space don't display it + if (text[chari] == ' ') continue; + } + + slices += width; + col += width; + HX1230_Draw(pdata,width); + + // Spacer between characters + if (col + 1 <= HX1230_COLS){ + HX1230_Draw((uint8_t*)"",1); + slices++; + col++; + } + } + + return slices; +} + +void HX1230_PrintField(uint8_t line, uint8_t colStart, uint8_t colEnd, const char* text, uint16_t length){ + HX1230_SetXY(colStart,line); + const uint8_t* pdata; + + uint8_t col = colStart; + + for(uint16_t chari = 0; chari < length; chari++){ + uint8_t width = getCharData(text[chari],&pdata); + if (col + width > colEnd){ + // Not fits in row + width = colEnd - col; + HX1230_Draw(pdata,width); + return; + } + + col += width; + HX1230_Draw(pdata,width); + + // Spacer between characters + if (col + 1 <= colEnd){ + col++; + HX1230_Draw((uint8_t*)"",1); + } + } + + while(col++ < colEnd){ + HX1230_Draw((uint8_t*)"",1); + } +} diff --git a/src/hx1230.h b/src/hx1230.h new file mode 100644 index 0000000..46d584f --- /dev/null +++ b/src/hx1230.h @@ -0,0 +1,47 @@ +#ifndef HX1230_H_ +#define HX1230_H_ + +#include "main.h" +#include "spi.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define HX1230_TURN_ON 0x2F +#define HX1230_TURN_OFF 0x28 + +#define HX1230_INVERT_ON 0xA7 +#define HX1230_INVERT_OFF 0xA6 + +#define HX1230_DISPLAY_ON 0xAF +#define HX1230_DISPLAY_OFF 0xAE + +#define HX1230_PIXEL_TEST_ON 0xA5 +#define HX1230_PIXEL_TEST_OFF 0xA4 + +#define HX1230_ROWS 9 +#define HX1230_COLS 96 + +void HX1230_Init(SPI_HandleTypeDef * hspi); + +void HX1230_Command(uint8_t cmd); +void HX1230_PixelTest(); +void HX1230_Stream(const uint16_t* data, uint16_t length); +void HX1230_Clear(); + +void HX1230_SetXY(uint8_t x, uint8_t y); +void HX1230_SetX(uint8_t x); +void HX1230_SetY(uint8_t y); +void HX1230_Scan_Offset(uint8_t y); + +void HX1230_Draw(const uint8_t* data, uint16_t length); + +uint16_t HX1230_Print(uint8_t x, uint8_t y, const char* text, uint16_t length); +void HX1230_PrintField(uint8_t line, uint8_t colStart, uint8_t colEnd, const char* text, uint16_t length); + +#ifdef __cplusplus +} +#endif + +#endif /* HX1230_H_ */ diff --git a/src/hx1230_menu.c b/src/hx1230_menu.c new file mode 100644 index 0000000..c5bae7d --- /dev/null +++ b/src/hx1230_menu.c @@ -0,0 +1,254 @@ +#include "hx1230_menu.h" + +#include "hx1230.h" + +#define SCREEN_HEIGHT (8) + +static struct submenu_t* menu = NULL; +static struct menu_option* selected = NULL; +static char str[30]; +static uint8_t len; + +static const uint8_t gfx_cursor[] = {0x00, 0x66, 0x3C, 0x18, 0x00}; +static const uint8_t gfx_btn_on[] = {0xE0, 0xF8, 0xF8, 0xE0, 0x00}; +static const uint8_t gfx_btn_off[] = {0xE0, 0xFE, 0xFE, 0xE0, 0x00}; +static const uint8_t gfx_tgl_on[] = {0xE0, 0xF0, 0xF8, 0xE6, 0x00}; +static const uint8_t gfx_tgl_off[] = {0xE6, 0xF8, 0xF0, 0xE0, 0x00}; +static const uint8_t gfx_slider[] = {0x08, 0xFE, 0xFE, 0x08, 0x00}; +static const uint8_t gfx_submenu[] = {0x00, 0xE0, 0x18, 0x06, 0x00}; +static const uint8_t gfx_mode[] = {0x10, 0x54, 0x38, 0x10, 0x00}; +static const uint8_t gfx_back[] = {0x10, 0x38, 0x54, 0x10, 0x00}; + +struct menu_controls controls = {}; + +static void deselect_loop(void* p){ + menu_deselect(); +} + +static void slider_loop(void* p); +static void slider_redraw(struct menu_slider *const slider); + +#define min(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + +#define max(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) + +// ----- + +void menu_init(struct submenu_t* _menu){ + if (!_menu || !_menu->options || !_menu->options[0].type) return; + menu = _menu; + if (!menu || menu->parent != _menu) menu->_cursor = 0; + menu->_scrn_cursor = 0; + selected = NULL; + + // find the number of menu items + if (!menu->_len){ + while(menu->options[++menu->_len].type); + } + + menu_redraw(); +} + +void menu_redraw(){ + // draw menu + + if (selected && (selected->type == MODE || selected->type == SLIDER)) return; + + HX1230_Clear(); + + uint16_t cursor = menu->_cursor - menu->_scrn_cursor; + uint8_t scrn_cursor = 0; + struct menu_option* option; + while(scrn_cursor < SCREEN_HEIGHT && cursor < menu->_len){ + if (menu->_scrn_cursor == scrn_cursor){ + HX1230_SetXY(0, scrn_cursor); + HX1230_Draw(gfx_cursor, NUMEL(gfx_cursor)); + } + + option = &menu->options[cursor]; + + HX1230_SetXY(NUMEL(gfx_cursor), scrn_cursor); + + switch(option->type){ + case VALUE: + len = sprintf(str, option->name, *(int16_t*)option->data); + break; + case MODE: + HX1230_Draw(gfx_mode, NUMEL(gfx_cursor)); + break; + case MENU: + HX1230_Draw(gfx_submenu, NUMEL(gfx_cursor)); + break; + case BACK: + HX1230_Draw(gfx_back, NUMEL(gfx_cursor)); + break; + case BUTTON: + HX1230_Draw((controls.enter && selected == option) ? gfx_btn_on : gfx_btn_off, NUMEL(gfx_cursor)); + break; + case TOGGLE: + HX1230_Draw(((struct menu_toggle*)option->data)->value ? gfx_tgl_on : gfx_tgl_off, NUMEL(gfx_cursor)); + break; + case SLIDER: + HX1230_Draw(gfx_slider, NUMEL(gfx_cursor)); + break; + default: + break; + } + + if (option->type != VALUE) + len = sprintf(str, option->name); + HX1230_PrintField(scrn_cursor, 2*NUMEL(gfx_cursor), HX1230_COLS, str, len); + + ++scrn_cursor; + ++cursor; + } +} + +void menu_up(){ + if (menu && menu->_cursor > 0) { + menu->_cursor--; + + if (menu->_scrn_cursor >= SCREEN_HEIGHT / 2) + menu->_scrn_cursor--; + + if (menu->_cursor < menu->_scrn_cursor) + menu->_scrn_cursor = menu->_cursor; + + menu_redraw(); + } +} + +void menu_down(){ + if (menu && menu->options[menu->_cursor+1].type != MENU_END) { + menu->_cursor++; + + if (menu->_scrn_cursor < SCREEN_HEIGHT / 2 || menu->_len < SCREEN_HEIGHT) + menu->_scrn_cursor++; + + if (menu->_len - menu->_cursor - 1 < min(SCREEN_HEIGHT, menu->_len) - 1 - menu->_scrn_cursor) + menu->_scrn_cursor = SCREEN_HEIGHT - 1 - (menu->_len - menu->_cursor - 1); + + menu_redraw(); + } +} + +void menu_select(){ + + if (!menu) return; + + selected = &menu->options[menu->_cursor]; + switch(selected->type){ + case MODE: + break; + case MENU: + menu_init((struct submenu_t*)selected->data); + break; + case BACK: + menu_init(menu->parent); + break; + case BUTTON: + { + struct menu_button *const button = (struct menu_button*)selected->data; + button->action(button->data); + selected->loop = &deselect_loop; + } + break; + case TOGGLE: + { + struct menu_toggle *const toggle = (struct menu_toggle*)selected->data; + toggle->value = !toggle->value; + selected->loop = &deselect_loop; + } + break; + case SLIDER: + // loop will handle the slider implementation + selected->loop = &slider_loop; + slider_redraw(selected->data); + break; + default: + // if not selectable, reject selecting menu item + selected = NULL; + break; + } + + menu_redraw(); +} + +void menu_deselect(){ + + if (!selected) return; + + selected = NULL; + menu_redraw(); +} + +void menu_loop(){ + if (selected && selected->loop) + selected->loop(selected->data); + + menu_refresh_controls(&controls); + + if (controls.enter_down == 1) + menu_redraw(); + + if (selected) return; + + if (!selected && controls.enter) menu_select(); + else { + if (controls.up) menu_up(); + if (controls.down) menu_down(); + } + + controls.up = controls.down = controls.plus = controls.minus = controls.enter = 0; +} + + +static uint8_t gfx_slider_ends[] = {0xFF, 0x81, 0xFF}; +static void slider_redraw(struct menu_slider *const slider){ + + // clear space between nubmer and slide + HX1230_PrintField(menu->_scrn_cursor, HX1230_COLS - 54 - 4, HX1230_COLS - 54, NULL, 0); + + len = sprintf(str, "%i", slider->value); + HX1230_PrintField(menu->_scrn_cursor, 2*NUMEL(gfx_cursor), HX1230_COLS - 54 - 4, str, len); + + HX1230_SetXY(HX1230_COLS - 54, menu->_scrn_cursor); + HX1230_Draw(&gfx_slider_ends[0], 2); + + uint8_t cols = 50; + uint8_t data = 0xBD; + uint8_t fill = ((slider->value - slider->min)*cols)/(slider->max - slider->min); + while(fill--){ + cols--; + HX1230_Draw(&data, 1); + } + data = 0x81; + while(cols--){ + HX1230_Draw(&data, 1); + } + + HX1230_Draw(&gfx_slider_ends[1], 2); +} + +static void slider_loop(void* p){ + struct menu_slider *const slider = (struct menu_slider*)p; + + if (controls.plus){ + slider->value = min(slider->max, slider->value + slider->step); + slider_redraw(slider); + } + + if (controls.minus){ + slider->value = max(slider->min, slider->value - slider->step); + slider_redraw(slider); + } + + if (controls.enter) menu_deselect(); +} + diff --git a/src/hx1230_menu.h b/src/hx1230_menu.h new file mode 100644 index 0000000..c63f7d2 --- /dev/null +++ b/src/hx1230_menu.h @@ -0,0 +1,85 @@ + +#ifndef MENU_H +#define MENU_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NUMEL(x) (sizeof(x)/sizeof(x[0])) + +typedef void(*menu_function)(void* data); + +typedef enum { + MENU_END = 0, + TITLE, + VALUE, + MODE, + MENU, + BACK, + BUTTON, + TOGGLE, + SLIDER, +} menu_option_type; + +struct menu_option{ + menu_option_type type; + const char* name; + menu_function loop; + void* data; +}; + +struct submenu_t{ + struct submenu_t* parent; + struct menu_option* options; + uint8_t _len; + uint8_t _cursor; + uint8_t _scrn_cursor; +}; + +struct menu_controls{ + char up; + char down; + char minus; + char plus; + char enter; + char enter_down; +}; + +struct menu_slider{ + int16_t value; + int16_t min; + int16_t max; + int16_t step; +}; + +struct menu_toggle{ + char value; +}; + +struct menu_button{ + menu_function action; + void* data; +}; + +void menu_init(struct submenu_t* menu); + +void menu_refresh_controls(struct menu_controls* controls); + +void menu_redraw(); + +void menu_select(); + +void menu_deselect(); + +void menu_loop(); + +extern struct menu_controls controls; + +#ifdef __cplusplus +} +#endif + +#endif /* MENU_H */