WIP, ui_menu
This commit is contained in:
parent
a6d091a7e5
commit
30ece44ea4
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -7,6 +7,9 @@
|
||||
"type_traits": "c",
|
||||
"gpio.h": "c",
|
||||
"stdint.h": "c",
|
||||
"time.h": "c"
|
||||
"time.h": "c",
|
||||
"st7735.h": "c",
|
||||
"stdbool.h": "c",
|
||||
"bmfont.h": "c"
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ typedef struct {
|
||||
int16_t char_y;
|
||||
uint32_t count;
|
||||
uint32_t unicode;
|
||||
uint8_t *utf8_text;
|
||||
const uint8_t *utf8_text;
|
||||
uint8_t last_char_width;
|
||||
uint8_t is_looping;
|
||||
} bmf_LoopState;
|
||||
@ -34,7 +34,7 @@ void place_next_char(bmf_BitmapFont *font, bmf_LoopState *state) {
|
||||
// get unicode char
|
||||
uint32_t b_off = state->byte_offset;
|
||||
uint32_t b_lim = state->byte_limit;
|
||||
uint8_t *utf8_text = state->utf8_text;
|
||||
const uint8_t *utf8_text = state->utf8_text;
|
||||
if (b_off >= b_lim) {
|
||||
state->is_looping = 0;
|
||||
state->unicode = bmf_ASCII_EOF;
|
||||
@ -77,7 +77,7 @@ void place_next_char(bmf_BitmapFont *font, bmf_LoopState *state) {
|
||||
state->char_y += font->char_height;
|
||||
state->char_x = state->start_x;
|
||||
}
|
||||
if (state->height_limit > 0 && (state->char_y + font->char_height - state->start_y > state->width_limit)) {
|
||||
if (state->height_limit > 0 && (state->char_y + font->char_height - state->start_y > state->height_limit)) {
|
||||
if (unicode == bmf_ASCII_N) {
|
||||
state->byte_offset = b_off;
|
||||
state->unicode = unicode;
|
||||
@ -94,7 +94,7 @@ void place_next_char(bmf_BitmapFont *font, bmf_LoopState *state) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t bmf_get_text_width(bmf_BitmapFont *font, uint8_t *text, uint32_t bytes_len) {
|
||||
uint16_t bmf_get_text_width(bmf_BitmapFont *font, const uint8_t *text, uint32_t bytes_len) {
|
||||
uint16_t total_width = 0;
|
||||
uint32_t b_off = 0;
|
||||
while (b_off < bytes_len) {
|
||||
@ -135,7 +135,7 @@ uint16_t bmf_get_text_width(bmf_BitmapFont *font, uint8_t *text, uint32_t bytes_
|
||||
return total_width;
|
||||
}
|
||||
|
||||
uint32_t bmf_draw_text(bmf_BitmapFont *font, uint8_t *text, uint32_t bytes_len, uint16_t x, uint16_t y, uint16_t width_limit, uint16_t height_limit, uint16_t color) {
|
||||
uint32_t bmf_draw_text(bmf_BitmapFont *font, const uint8_t *text, uint32_t bytes_len, uint16_t x, uint16_t y, uint16_t width_limit, uint16_t height_limit, uint16_t color) {
|
||||
bmf_LoopState state_obj = {bytes_len, 0, x, y, width_limit, height_limit, x, y, 0, 0, text, 0, 1};
|
||||
bmf_LoopState *state = &state_obj;
|
||||
bmf_FunctionGetCharImage get_char_image = font->get_char_image;
|
||||
@ -178,7 +178,7 @@ uint32_t bmf_draw_text(bmf_BitmapFont *font, uint8_t *text, uint32_t bytes_len,
|
||||
return state_obj.byte_offset;
|
||||
}
|
||||
|
||||
uint32_t bmf_get_text_offset(bmf_BitmapFont *font, uint8_t *text, uint32_t bytes_len, uint16_t width_limit, uint16_t height_limit) {
|
||||
uint32_t bmf_get_text_offset(bmf_BitmapFont *font, const uint8_t *text, uint32_t bytes_len, uint16_t width_limit, uint16_t height_limit) {
|
||||
bmf_LoopState state_obj = {bytes_len, 0, 0, 0, width_limit, height_limit, 0, 0, 0, 0, text, 0, 1};
|
||||
bmf_LoopState *state = &state_obj;
|
||||
while (state_obj.is_looping) {
|
||||
|
@ -14,6 +14,6 @@ typedef struct bmf_BitmapFont {
|
||||
const uint8_t *ascii_width; // size [94]
|
||||
} bmf_BitmapFont;
|
||||
|
||||
uint16_t bmf_get_text_width(bmf_BitmapFont *font, uint8_t *text, uint32_t bytes_len);
|
||||
uint32_t bmf_draw_text(bmf_BitmapFont *font, uint8_t *text, uint32_t bytes_len, uint16_t x, uint16_t y, uint16_t width_limit, uint16_t height_limit, uint16_t color);
|
||||
uint32_t bmf_get_text_offset(bmf_BitmapFont *font, uint8_t *text, uint32_t bytes_len, uint16_t width_limit, uint16_t height_limit);
|
||||
uint16_t bmf_get_text_width(bmf_BitmapFont *font, const uint8_t *text, uint32_t bytes_len);
|
||||
uint32_t bmf_draw_text(bmf_BitmapFont *font, const uint8_t *text, uint32_t bytes_len, uint16_t x, uint16_t y, uint16_t width_limit, uint16_t height_limit, uint16_t color);
|
||||
uint32_t bmf_get_text_offset(bmf_BitmapFont *font, const uint8_t *text, uint32_t bytes_len, uint16_t width_limit, uint16_t height_limit);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <stdint.h>
|
||||
#include "monoimg.h"
|
||||
#include "st7735.h"
|
||||
|
||||
#define max(a,b) ((a) >= (b) ? (a) : (b))
|
||||
#define min(a,b) ((a) <= (b) ? (a) : (b))
|
||||
@ -23,7 +24,7 @@ uint8_t mimg_get_pixel(const uint8_t *img, uint16_t x, uint16_t y) {
|
||||
return mimg_get_pixel_unsafe(img, (uint8_t)x, (uint8_t)y);
|
||||
}
|
||||
|
||||
void mimg_draw(mimg_FunctionSetPixel set_pixel, uint16_t x, uint16_t y, uint16_t color, const uint8_t *img, mimg_Area area) {
|
||||
void mimg_draw(uint16_t x, uint16_t y, uint16_t color, const uint8_t *img, mimg_Area area) {
|
||||
uint8_t width_s1 = img[0]; // width - 1
|
||||
uint8_t height_s1 = img[1]; // height - 1
|
||||
uint8_t ix = min(area.x, width_s1);
|
||||
@ -34,13 +35,13 @@ void mimg_draw(mimg_FunctionSetPixel set_pixel, uint16_t x, uint16_t y, uint16_t
|
||||
for (off_y = 0; off_y < ih; off_y ++) {
|
||||
for (off_x = 0; off_x < iw; off_x ++) {
|
||||
if (mimg_get_pixel_unsafe(img, ix + off_x, iy + off_y)) {
|
||||
set_pixel(x + off_x, y + off_y, color);
|
||||
ST7735_DrawPixel(x + off_x, y + off_y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mimg_draw_with_bg(mimg_FunctionSetPixel set_pixel, uint16_t x, uint16_t y, uint16_t color, uint16_t bg_color, const uint8_t *img, mimg_Area area) {
|
||||
void mimg_draw_with_bg(uint16_t x, uint16_t y, uint16_t color, uint16_t bg_color, const uint8_t *img, mimg_Area area) {
|
||||
uint8_t width_s1 = img[0]; // width - 1
|
||||
uint8_t height_s1 = img[1]; // height - 1
|
||||
uint8_t ix = min(area.x, width_s1);
|
||||
@ -48,15 +49,22 @@ void mimg_draw_with_bg(mimg_FunctionSetPixel set_pixel, uint16_t x, uint16_t y,
|
||||
uint8_t iw = min(area.w, width_s1 - ix + 1);
|
||||
uint8_t ih = min(area.h, height_s1 - iy + 1);
|
||||
uint8_t off_x, off_y;
|
||||
ST7735_Select();
|
||||
ST7735_SetAddressWindow(x, y, x + iw - 1, y + ih - 1);
|
||||
ST7735_WriteCommand(ST7735_RAMWR);
|
||||
HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_SET);
|
||||
uint8_t data_color[] = {color >> 8, color & 0xFF};
|
||||
uint8_t data_bg_color[] = {bg_color >> 8, bg_color & 0xFF};
|
||||
for (off_y = 0; off_y < ih; off_y ++) {
|
||||
for (off_x = 0; off_x < iw; off_x ++) {
|
||||
if (mimg_get_pixel_unsafe(img, ix + off_x, iy + off_y)) {
|
||||
set_pixel(x + off_x, y + off_y, color);
|
||||
HAL_SPI_Transmit(&ST7735_SPI_PORT, data_color, sizeof(data_color), HAL_MAX_DELAY);
|
||||
} else {
|
||||
set_pixel(x + off_x, y + off_y, bg_color);
|
||||
HAL_SPI_Transmit(&ST7735_SPI_PORT, data_bg_color, sizeof(data_bg_color), HAL_MAX_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
ST7735_Unselect();
|
||||
}
|
||||
|
||||
mimg_Area mimg_get_tile_area(const uint8_t *img, uint8_t cols, uint8_t rows, uint8_t index) {
|
||||
|
@ -14,7 +14,7 @@ typedef struct mimg_Area
|
||||
/** get a pixel from img, return 1 or 0 */
|
||||
uint8_t mimg_get_pixel(const uint8_t *img, uint16_t x, uint16_t y);
|
||||
/** draw a part of img {ix, iy, iw, ih} , at (x, y) with color */
|
||||
void mimg_draw(mimg_FunctionSetPixel set_pixel, uint16_t x, uint16_t y, uint16_t color, const uint8_t *img, mimg_Area area);
|
||||
void mimg_draw_with_bg(mimg_FunctionSetPixel set_pixel, uint16_t x, uint16_t y, uint16_t color, uint16_t bg_color, const uint8_t *img, mimg_Area area);
|
||||
void mimg_draw(uint16_t x, uint16_t y, uint16_t color, const uint8_t *img, mimg_Area area);
|
||||
void mimg_draw_with_bg(uint16_t x, uint16_t y, uint16_t color, uint16_t bg_color, const uint8_t *img, mimg_Area area);
|
||||
/** calc tile area */
|
||||
mimg_Area mimg_get_tile_area(const uint8_t *img, uint8_t cols, uint8_t rows, uint8_t index);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "monoimg.h"
|
||||
#include "bmfont.h"
|
||||
#include "asciifont.h"
|
||||
#include "ui_utils.h"
|
||||
|
||||
void ui_text_number18x32(uint32_t num, uint16_t x, uint16_t y, uint16_t color) {
|
||||
uint32_t tmp = num;
|
||||
@ -21,12 +22,12 @@ void ui_text_number18x32(uint32_t num, uint16_t x, uint16_t y, uint16_t color) {
|
||||
div = div / 10;
|
||||
if (div == 0) {
|
||||
mimg_Area area = mimg_get_tile_area(IMG_DIGI_18_32, 10, 1, 0);
|
||||
mimg_draw(ST7735_DrawPixel, x, y, color, IMG_DIGI_18_32, area);
|
||||
mimg_draw(x, y, color, IMG_DIGI_18_32, area);
|
||||
} else {
|
||||
while (div > 0) {
|
||||
tmp = (num / div) % 10;
|
||||
mimg_Area area = mimg_get_tile_area(IMG_DIGI_18_32, 10, 1, tmp);
|
||||
mimg_draw(ST7735_DrawPixel, x, y, color, IMG_DIGI_18_32, area);
|
||||
mimg_draw(x, y, color, IMG_DIGI_18_32, area);
|
||||
x = x + 18;
|
||||
div = div / 10;
|
||||
}
|
||||
@ -45,12 +46,12 @@ void ui_text_number18x32_with_bg(uint32_t num, uint16_t x, uint16_t y, uint16_t
|
||||
div = div / 10;
|
||||
if (div == 0) {
|
||||
mimg_Area area = mimg_get_tile_area(IMG_DIGI_18_32, 10, 1, 0);
|
||||
mimg_draw_with_bg(ST7735_DrawPixel, x, y, color, bg_color, IMG_DIGI_18_32, area);
|
||||
mimg_draw_with_bg(x, y, color, bg_color, IMG_DIGI_18_32, area);
|
||||
} else {
|
||||
while (div > 0) {
|
||||
tmp = (num / div) % 10;
|
||||
mimg_Area area = mimg_get_tile_area(IMG_DIGI_18_32, 10, 1, tmp);
|
||||
mimg_draw_with_bg(ST7735_DrawPixel, x, y, color, bg_color, IMG_DIGI_18_32, area);
|
||||
mimg_draw_with_bg(x, y, color, bg_color, IMG_DIGI_18_32, area);
|
||||
x = x + 18;
|
||||
div = div / 10;
|
||||
}
|
||||
@ -205,7 +206,7 @@ void icon_stereo() {
|
||||
if (global_data.flag & G_FL_MONO) {
|
||||
ST7735_FillRectangle(8, 25, area.w, area.h, ST7735_BLACK);
|
||||
} else {
|
||||
mimg_draw_with_bg(ST7735_DrawPixel, 8, 25, ST7735_YELLOW, ST7735_BLACK, IMG_STEREO, area);
|
||||
mimg_draw_with_bg(8, 25, ST7735_YELLOW, ST7735_BLACK, IMG_STEREO, area);
|
||||
}
|
||||
}
|
||||
|
||||
|
175
Core/App/Graphic/ui_menu.c
Normal file
175
Core/App/Graphic/ui_menu.c
Normal file
@ -0,0 +1,175 @@
|
||||
#include <stdint.h>
|
||||
#include "keypad.h"
|
||||
#include "st7735.h"
|
||||
#include "asciifont.h"
|
||||
#include "ui_menu.h"
|
||||
#include "ui_utils.h"
|
||||
|
||||
#define LIST_STYLE_SELECTED_COLOR_BG ST7735_COLOR565(0x40, 0x40, 0x40)
|
||||
#define LIST_STYLE_OFFSET_LEFT 32
|
||||
#define UI_HALF_Y (UI_Y + (UI_H / 2))
|
||||
#define LIST_PAGE_SIZE (UI_H / font_unifont_8x16->char_height)
|
||||
#define LIST_PAGE_SIZE_HALF ((LIST_PAGE_SIZE + 1) / 2)
|
||||
#define LIST_ITEM_LEVEL(p) ((p < LIST_PAGE_SIZE_HALF) ? (p) : (LIST_PAGE_SIZE - p - 1))
|
||||
#define UI_LIST_OFFSET_X(p) (UI_X + (LIST_STYLE_OFFSET_LEFT * LIST_ITEM_LEVEL(p) / (LIST_PAGE_SIZE_HALF - 1)) + 8)
|
||||
#define UI_LIST_OFFSET_Y(p) (UI_Y + (font_unifont_8x16->char_height * p))
|
||||
#define UI_LIST_WIDTH(p) (UI_W - (LIST_STYLE_OFFSET_LEFT * LIST_ITEM_LEVEL(p) / (LIST_PAGE_SIZE_HALF - 1)) - 8)
|
||||
|
||||
#define U8_RESET 255
|
||||
/*
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
*/
|
||||
static uint16_t get_item_count(uiu_GetStrItemFunc get_item) {
|
||||
uint16_t len = 0;
|
||||
while (get_item(len).len > 0) {
|
||||
len ++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static void render_page_number(uint8_t curr, uint8_t total) {
|
||||
uint8_t number_str[4] = {0, 0, 0, 0};
|
||||
uint8_t scale = 100;
|
||||
uint8_t num_pos = 0;
|
||||
while (scale > 0) {
|
||||
uint8_t num = (curr / scale) % 10;
|
||||
scale /= 10;
|
||||
if (num == 0 && num_pos == 0) continue;
|
||||
number_str[num_pos] = '0' + num;
|
||||
num_pos ++;
|
||||
}
|
||||
uiu_text_area(font_quan_8x8, number_str, 4,
|
||||
UI_X, UI_HALF_Y - 1 - font_quan_8x8->char_height - 1,
|
||||
font_quan_8x8->char_width * 3, font_quan_8x8->char_height,
|
||||
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_YELLOW, ST7735_BLACK
|
||||
);
|
||||
number_str[0] = 0;
|
||||
number_str[1] = 0;
|
||||
number_str[2] = 0;
|
||||
number_str[3] = 0;
|
||||
scale = 100;
|
||||
num_pos = 0;
|
||||
while (scale > 0) {
|
||||
uint8_t num = (total / scale) % 10;
|
||||
scale /= 10;
|
||||
if (num == 0 && num_pos == 0) continue;
|
||||
number_str[num_pos] = '0' + num;
|
||||
num_pos ++;
|
||||
}
|
||||
uiu_text_area(font_quan_8x8, number_str, 4,
|
||||
UI_X, UI_HALF_Y + 2,
|
||||
font_quan_8x8->char_width * 3, font_quan_8x8->char_height,
|
||||
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_YELLOW, ST7735_BLACK
|
||||
);
|
||||
}
|
||||
|
||||
IndexResult iui_list_select(const uint8_t *title, uint32_t len, uiu_GetStrItemFunc get_item, uint16_t init_index) {
|
||||
uint16_t item_count = get_item_count(get_item);
|
||||
uint16_t pointer = init_index % item_count;
|
||||
uint8_t tmp_pointer = U8_RESET;
|
||||
uint8_t last_pointer = U8_RESET;
|
||||
uint16_t page_start = (pointer / LIST_PAGE_SIZE) * LIST_PAGE_SIZE;
|
||||
printf("item count: %u\n", item_count);
|
||||
// clear
|
||||
ST7735_FillScreen(ST7735_BLACK);
|
||||
// render title
|
||||
uiu_title(title, len);
|
||||
// render line
|
||||
ST7735_DrawLine(UI_X, UI_Y + font_unifont_8x16->char_height, LIST_STYLE_OFFSET_LEFT - 1, UI_HALF_Y - 1, ST7735_YELLOW);
|
||||
ST7735_DrawLine(UI_X, UI_Y + UI_H - font_unifont_8x16->char_height - 1, LIST_STYLE_OFFSET_LEFT - 1, UI_HALF_Y, ST7735_YELLOW);
|
||||
ST7735_FillRectangle(UI_X, UI_HALF_Y - 1, LIST_STYLE_OFFSET_LEFT - 1, 1, ST7735_YELLOW);
|
||||
while (1) {
|
||||
uint8_t event = kp_query();
|
||||
uint8_t et = kp_Type(event);
|
||||
uint8_t ev = kp_Value(event);
|
||||
// process event
|
||||
if (et == kp_ROTATE_RIGHT || et == kp_ROTATE_LEFT) {
|
||||
if (et == kp_ROTATE_RIGHT) {
|
||||
pointer += ev;
|
||||
} else {
|
||||
pointer += (0x7FFF / item_count) * item_count;
|
||||
pointer -= ev;
|
||||
}
|
||||
pointer %= item_count;
|
||||
if (((pointer / LIST_PAGE_SIZE) * LIST_PAGE_SIZE) != page_start) {
|
||||
last_pointer = U8_RESET;
|
||||
page_start = ((pointer / LIST_PAGE_SIZE) * LIST_PAGE_SIZE);
|
||||
}
|
||||
tmp_pointer = U8_RESET;
|
||||
printf("Move list pointer to %u\n", pointer);
|
||||
} else if (et == kp_SHORT_CLICK) {
|
||||
if (ev == kp_KEYENCODER) {
|
||||
discare_kp_events();
|
||||
printf("Confirm list item %u\n", pointer);
|
||||
IndexResult ret = {pointer, 1};
|
||||
return ret;
|
||||
}
|
||||
} else if (et == kp_LONG_PRESS) {
|
||||
if (ev == kp_KEYENCODER) {
|
||||
discare_kp_events();
|
||||
printf("Cancel list item %u\n", pointer);
|
||||
IndexResult ret = {pointer, 0};
|
||||
return ret;
|
||||
}
|
||||
} else if (et != kp_NOP) {
|
||||
printf("Unhandled event: %u %u\n", et, ev);
|
||||
}
|
||||
// render items
|
||||
if (tmp_pointer == U8_RESET) {
|
||||
// need render
|
||||
if (last_pointer == U8_RESET) {
|
||||
// render all
|
||||
render_page_number((pointer / LIST_PAGE_SIZE) + 1, (item_count + LIST_PAGE_SIZE - 1) / LIST_PAGE_SIZE);
|
||||
for (tmp_pointer = 0; tmp_pointer < LIST_PAGE_SIZE; tmp_pointer ++) {
|
||||
uint16_t current = page_start + tmp_pointer;
|
||||
if (current >= item_count) {
|
||||
uiu_text_area(font_unifont_8x16, u8str(" "), 1,
|
||||
UI_LIST_OFFSET_X(tmp_pointer), UI_LIST_OFFSET_Y(tmp_pointer),
|
||||
UI_LIST_WIDTH(tmp_pointer), font_unifont_8x16->char_height,
|
||||
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_WHITE, ST7735_BLACK
|
||||
);
|
||||
continue;
|
||||
}
|
||||
StrItem item = get_item(current);
|
||||
if (current == pointer) {
|
||||
uiu_text_area(font_unifont_8x16, item.text, item.len,
|
||||
UI_LIST_OFFSET_X(tmp_pointer), UI_LIST_OFFSET_Y(tmp_pointer),
|
||||
UI_LIST_WIDTH(tmp_pointer), font_unifont_8x16->char_height,
|
||||
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_GREEN, LIST_STYLE_SELECTED_COLOR_BG
|
||||
);
|
||||
last_pointer = tmp_pointer;
|
||||
} else {
|
||||
uiu_text_area(font_unifont_8x16, item.text, item.len,
|
||||
UI_LIST_OFFSET_X(tmp_pointer), UI_LIST_OFFSET_Y(tmp_pointer),
|
||||
UI_LIST_WIDTH(tmp_pointer), font_unifont_8x16->char_height,
|
||||
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_WHITE, ST7735_BLACK
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
StrItem item = get_item(page_start + last_pointer);
|
||||
uiu_text_area(font_unifont_8x16, item.text, item.len,
|
||||
UI_LIST_OFFSET_X(last_pointer), UI_LIST_OFFSET_Y(last_pointer),
|
||||
UI_LIST_WIDTH(last_pointer), font_unifont_8x16->char_height,
|
||||
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_WHITE, ST7735_BLACK
|
||||
);
|
||||
last_pointer = pointer - page_start;
|
||||
StrItem item_curr = get_item(pointer);
|
||||
uiu_text_area(font_unifont_8x16, item_curr.text, item_curr.len,
|
||||
UI_LIST_OFFSET_X(last_pointer), UI_LIST_OFFSET_Y(last_pointer),
|
||||
UI_LIST_WIDTH(last_pointer), font_unifont_8x16->char_height,
|
||||
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_GREEN, LIST_STYLE_SELECTED_COLOR_BG
|
||||
);
|
||||
}
|
||||
tmp_pointer = 0;
|
||||
}
|
||||
}
|
||||
}
|
5
Core/App/Graphic/ui_menu.h
Normal file
5
Core/App/Graphic/ui_menu.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "ui_utils.h"
|
||||
|
||||
IndexResult iui_list_select(const uint8_t *title, uint32_t len, uiu_GetStrItemFunc get_item, uint16_t init_index);
|
60
Core/App/Graphic/ui_utils.c
Normal file
60
Core/App/Graphic/ui_utils.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include <stdint.h>
|
||||
#include "ui_utils.h"
|
||||
#include "st7735.h"
|
||||
#include "bmfont.h"
|
||||
#include "asciifont.h"
|
||||
|
||||
#define MAX_LINES 16
|
||||
#define TITLE_COLOR_BG ST7735_COLOR565(0x20, 0x20, 0x20)
|
||||
|
||||
const StrItem NULL_STR_ITEM = { NULL, 0 };
|
||||
|
||||
void uiu_text_area(bmf_BitmapFont *font, const uint8_t *text, uint32_t len, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t align, uint16_t color, uint16_t bg_color) {
|
||||
// calc line width
|
||||
uint16_t lws[MAX_LINES];
|
||||
uint16_t gws[MAX_LINES];
|
||||
uint16_t max_width = 0;
|
||||
uint8_t lines = 0;
|
||||
uint16_t p_off = 0;
|
||||
while ((p_off < len) && ((lines + 1) * font->char_height <= h) && (lines < MAX_LINES)) {
|
||||
uint16_t fitlen = bmf_get_text_offset(font, text + p_off, len - p_off, w, font->char_height);
|
||||
if (fitlen == 0) {
|
||||
break;
|
||||
}
|
||||
lws[lines] = fitlen;
|
||||
gws[lines] = bmf_get_text_width(font, text + p_off, fitlen);
|
||||
max_width = (gws[lines] > max_width) ? gws[lines] : max_width;
|
||||
lines ++;
|
||||
p_off += fitlen;
|
||||
}
|
||||
// draw lines
|
||||
uint16_t off_x = 0;
|
||||
uint16_t off_y = 0;
|
||||
if (align & uiu_ALIGN_VBOTTOM) {
|
||||
off_y = y + (h - (lines * font->char_height));
|
||||
}else if (align & uiu_ALIGN_VCENTER) {
|
||||
off_y = y + ((h - (lines * font->char_height)) / 2);
|
||||
}else {
|
||||
off_y = y;
|
||||
}
|
||||
uint8_t cur_lines;
|
||||
p_off = 0;
|
||||
ST7735_FillRectangle(x, y, w, h, bg_color);
|
||||
for (cur_lines = 0; cur_lines < lines; cur_lines ++) {
|
||||
if (align & uiu_ALIGN_HRIGHT) {
|
||||
off_x = x + (w - gws[cur_lines]);
|
||||
} else if (align & uiu_ALIGN_HCENTER) {
|
||||
off_x = x + ((w - gws[cur_lines]) / 2);
|
||||
} else {
|
||||
off_x = x;
|
||||
}
|
||||
bmf_draw_text(font, text + p_off, lws[cur_lines], off_x, off_y, gws[cur_lines], font->char_height, color);
|
||||
off_y += font->char_height;
|
||||
p_off += lws[cur_lines];
|
||||
}
|
||||
}
|
||||
|
||||
void uiu_title(const uint8_t *text, uint32_t len) {
|
||||
ST7735_FillRectangle(0, 0, ST7735_WIDTH, 16, TITLE_COLOR_BG);
|
||||
uiu_text_area(font_unifont_8x16, text, len, 0, 0, ST7735_WIDTH, 16, uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_YELLOW, TITLE_COLOR_BG);
|
||||
}
|
41
Core/App/Graphic/ui_utils.h
Normal file
41
Core/App/Graphic/ui_utils.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "bmfont.h"
|
||||
#include "st7735.h"
|
||||
|
||||
#define uiu_ALIGN_HLEFT 0b00000001
|
||||
#define uiu_ALIGN_HCENTER 0b00000010
|
||||
#define uiu_ALIGN_HRIGHT 0b00000100
|
||||
#define uiu_ALIGN_VTOP 0b00010000
|
||||
#define uiu_ALIGN_VCENTER 0b00100000
|
||||
#define uiu_ALIGN_VBOTTOM 0b01000000
|
||||
|
||||
#define UI_X 0
|
||||
#define UI_Y 16
|
||||
#define UI_W (ST7735_WIDTH)
|
||||
#define UI_H (ST7735_HEIGHT - 16)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const uint8_t *text;
|
||||
const uint32_t len;
|
||||
} StrItem;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t index;
|
||||
uint8_t confirmed;
|
||||
} IndexResult;
|
||||
|
||||
|
||||
extern const StrItem NULL_STR_ITEM;
|
||||
|
||||
/** get string item in the list.
|
||||
* @param index item index
|
||||
* @return STR_ITEM, if STR_ITEM.len == 0 means item not exist.
|
||||
*/
|
||||
typedef StrItem (*uiu_GetStrItemFunc)(uint16_t index);
|
||||
|
||||
void uiu_text_area(bmf_BitmapFont *font, const uint8_t *text, uint32_t len, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t align, uint16_t color, uint16_t bg_color);
|
||||
void uiu_title(const uint8_t *text, uint32_t len);
|
@ -92,3 +92,10 @@ uint8_t kp_query() {
|
||||
}
|
||||
return K_EVENT(kp_NOP, 0);
|
||||
}
|
||||
|
||||
void discare_kp_events() {
|
||||
uint8_t event = kp_query();
|
||||
while (kp_Type(event) != kp_NOP) {
|
||||
event = kp_query();
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,8 @@
|
||||
#define kp_Type(x) (x & 0b1111)
|
||||
#define kp_Value(x) (x >> 4)
|
||||
|
||||
#define kp_LONG_PRESS_TIMEOUT_MS 250
|
||||
#define kp_LONG_PRESS_TIMEOUT_MS 500
|
||||
|
||||
// query and return keypad event
|
||||
uint8_t kp_query();
|
||||
void discare_kp_events(void);
|
||||
|
@ -6,6 +6,39 @@
|
||||
#include "time.h"
|
||||
#include "kt0915.h"
|
||||
|
||||
/** test */
|
||||
#include "ui_menu.h"
|
||||
#include "ui_utils.h"
|
||||
|
||||
static const uint8_t *item_text = u8str("qwertyuiop");
|
||||
static StrItem app_get_item(uint16_t index) {
|
||||
if (index >= 10) {
|
||||
return NULL_STR_ITEM;
|
||||
}
|
||||
StrItem item = { item_text, 1 };
|
||||
item.text += index;
|
||||
return item;
|
||||
}
|
||||
|
||||
void test() {
|
||||
ST7735_FillScreen(ST7735_BLACK);
|
||||
printf("test start.\n");
|
||||
while (1) {
|
||||
IndexResult res = iui_list_select(u8str("Kobold's Menu"), 33, app_get_item, 0);
|
||||
printf("You Selected '%s'\n", app_get_item(res.index).text);
|
||||
if (res.confirmed) {
|
||||
printf("and you confirmed it.\n");
|
||||
} else {
|
||||
printf("but you canceled it.\n");
|
||||
}
|
||||
}
|
||||
// end
|
||||
printf("test end.\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
/** test end */
|
||||
|
||||
void __limit_freq_range() {
|
||||
uint16_t limit_min = (global_data.rf_mode == G_RF_MODE_AM) ? G_AM_FREQ_MIN : G_FM_FREQ_MIN;
|
||||
uint16_t limit_max = (global_data.rf_mode == G_RF_MODE_AM) ? G_AM_FREQ_MAX : G_FM_FREQ_MAX;
|
||||
@ -16,6 +49,14 @@ void __limit_freq_range() {
|
||||
}
|
||||
}
|
||||
|
||||
void __ensure_mute() {
|
||||
if (global_data.flag & G_FL_MUTE) {
|
||||
KT0915_setAudioMute(1);
|
||||
} else {
|
||||
KT0915_setAudioMute(0);
|
||||
}
|
||||
}
|
||||
|
||||
void __send_freq() {
|
||||
if (global_data.rf_mode == G_RF_MODE_AM) {
|
||||
KT0915_setFrequency(global_data.freq);
|
||||
@ -35,12 +76,14 @@ void __switch_to_fm() {
|
||||
KT0915_setFM(G_FM_FREQ_MIN * 50ul, G_FM_FREQ_MAX * 50ul, G_FM_FREQ_MIN * 50ul, 50u);
|
||||
printf("Switched to FM Mode\n");
|
||||
__send_freq();
|
||||
__ensure_mute();
|
||||
}
|
||||
|
||||
void __switch_to_am() {
|
||||
KT0915_setAM(G_AM_FREQ_MIN, G_AM_FREQ_MAX, G_AM_FREQ_MIN, 1, 0);
|
||||
printf("Switched to AM Mode\n");
|
||||
__send_freq();
|
||||
__ensure_mute();
|
||||
}
|
||||
|
||||
uint16_t __read_rssi() {
|
||||
@ -78,8 +121,9 @@ void app_init() {
|
||||
printf("\n====start====\n");
|
||||
target_time_stamp = ticks_add(ticks_ms(), 500);
|
||||
kp_query();
|
||||
__init_kt0915();
|
||||
ui_screen_main();
|
||||
// __init_kt0915();
|
||||
// ui_screen_main();
|
||||
test();
|
||||
}
|
||||
|
||||
void app_main_loop() {
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "global.h"
|
||||
|
||||
GlobalData global_data = {
|
||||
0b0000000000000000, //flag
|
||||
0b0000000000000001, //flag
|
||||
// 880 * 2, // freq
|
||||
893 * 2, // freq
|
||||
G_RF_MODE_FM, //rf_mode
|
||||
|
@ -77,7 +77,7 @@ static const uint8_t
|
||||
ST7735_DISPON, DELAY, // 4: Main screen turn on, no args w/delay
|
||||
100}; // 100 ms delay
|
||||
|
||||
static void ST7735_Select()
|
||||
void ST7735_Select()
|
||||
{
|
||||
HAL_GPIO_WritePin(ST7735_CS_GPIO_Port, ST7735_CS_Pin, GPIO_PIN_RESET);
|
||||
}
|
||||
@ -87,21 +87,21 @@ void ST7735_Unselect()
|
||||
HAL_GPIO_WritePin(ST7735_CS_GPIO_Port, ST7735_CS_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
static void ST7735_Reset()
|
||||
void ST7735_Reset()
|
||||
{
|
||||
HAL_GPIO_WritePin(ST7735_RES_GPIO_Port, ST7735_RES_Pin, GPIO_PIN_RESET);
|
||||
HAL_Delay(5);
|
||||
HAL_GPIO_WritePin(ST7735_RES_GPIO_Port, ST7735_RES_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
static void ST7735_WriteCommand(uint8_t cmd)
|
||||
void ST7735_WriteCommand(uint8_t cmd)
|
||||
{
|
||||
HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(&ST7735_SPI_PORT, &cmd, sizeof(cmd), HAL_MAX_DELAY);
|
||||
// SPI_Write(&cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static void ST7735_WriteData(uint8_t *buff, size_t buff_size)
|
||||
void ST7735_WriteData(uint8_t *buff, size_t buff_size)
|
||||
{
|
||||
HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_SET);
|
||||
HAL_SPI_Transmit(&ST7735_SPI_PORT, buff, buff_size, HAL_MAX_DELAY);
|
||||
@ -139,7 +139,7 @@ static void ST7735_ExecuteCommandList(const uint8_t *addr)
|
||||
}
|
||||
}
|
||||
|
||||
static void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
|
||||
void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
|
||||
{
|
||||
// column address set
|
||||
ST7735_WriteCommand(ST7735_CASET);
|
||||
@ -178,54 +178,61 @@ void ST7735_DrawPixel(uint16_t x, uint16_t y, uint16_t color) //画点
|
||||
ST7735_Unselect();
|
||||
}
|
||||
|
||||
void ST7735_DrawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,uint16_t color) //画线
|
||||
void ST7735_DrawLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2,uint16_t color)
|
||||
{
|
||||
int16_t temp;
|
||||
int16_t steep = abs(y1 - y0) > abs(x1 - x0);
|
||||
if (steep) {
|
||||
temp = x0;
|
||||
x0 = y0;
|
||||
y0 = temp;
|
||||
|
||||
temp = x1;
|
||||
x0 = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
|
||||
if (x0 > x1) {
|
||||
temp = x1;
|
||||
x1 = x0;
|
||||
x0 = temp;
|
||||
|
||||
temp = y1;
|
||||
y1 = y0;
|
||||
y0 = temp;
|
||||
}
|
||||
|
||||
int16_t dx, dy;
|
||||
dx = x1 - x0;
|
||||
dy = abs(y1 - y0);
|
||||
|
||||
int16_t err = dx / 2;
|
||||
int16_t ystep;
|
||||
|
||||
if (y0 < y1) {
|
||||
ystep = 1;
|
||||
int16_t dx = x2 - x1;
|
||||
int16_t sx;
|
||||
if (dx > 0) {
|
||||
sx = 1;
|
||||
} else {
|
||||
ystep = -1;
|
||||
dx = -dx;
|
||||
sx = -1;
|
||||
}
|
||||
|
||||
for (; x0 <= x1; x0++) {
|
||||
int16_t dy = y2 - y1;
|
||||
int16_t sy;
|
||||
if (dy > 0) {
|
||||
sy = 1;
|
||||
} else {
|
||||
dy = -dy;
|
||||
sy = -1;
|
||||
}
|
||||
uint8_t steep;
|
||||
if (dy > dx) {
|
||||
int16_t temp;
|
||||
temp = x1;
|
||||
x1 = y1;
|
||||
y1 = temp;
|
||||
temp = dx;
|
||||
dx = dy;
|
||||
dy = temp;
|
||||
temp = sx;
|
||||
sx = sy;
|
||||
sy = temp;
|
||||
steep = 1;
|
||||
} else {
|
||||
steep = 0;
|
||||
}
|
||||
int16_t e = 2 * dy - dx;
|
||||
int16_t i;
|
||||
for (i = 0; i < dx; ++i) {
|
||||
if (steep) {
|
||||
ST7735_DrawPixel(y0, x0, color);
|
||||
if (0 <= y1 && y1 < ST7735_WIDTH && 0 <= x1 && x1 < ST7735_HEIGHT) {
|
||||
ST7735_DrawPixel(y1, x1, color);
|
||||
}
|
||||
} else {
|
||||
ST7735_DrawPixel(x0, y0, color);
|
||||
if (0 <= x1 && x1 < ST7735_WIDTH && 0 <= y1 && y1 < ST7735_HEIGHT) {
|
||||
ST7735_DrawPixel(x1, y1, color);
|
||||
}
|
||||
}
|
||||
err -= dy;
|
||||
if (err < 0) {
|
||||
y0 += ystep;
|
||||
err += dx;
|
||||
while (e >= 0) {
|
||||
y1 += sy;
|
||||
e -= 2 * dx;
|
||||
}
|
||||
x1 += sx;
|
||||
e += 2 * dy;
|
||||
}
|
||||
if (0 <= x2 && x2 < ST7735_WIDTH && 0 <= y2 && y2 < ST7735_HEIGHT) {
|
||||
ST7735_DrawPixel(x2, y2, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,6 +237,11 @@ extern SPI_HandleTypeDef ST7735_SPI_PORT;
|
||||
|
||||
// call before initializing any SPI devices
|
||||
void ST7735_Unselect(void);
|
||||
void ST7735_Select(void);
|
||||
void ST7735_Reset(void);
|
||||
void ST7735_WriteCommand(uint8_t cmd);
|
||||
void ST7735_WriteData(uint8_t *buff, size_t buff_size);
|
||||
void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);
|
||||
|
||||
void ST7735_Init(void);
|
||||
void ST7735_DrawPixel(uint16_t x, uint16_t y, uint16_t color);
|
||||
|
9
Makefile
9
Makefile
@ -76,6 +76,8 @@ Core/Hardware/ST7735/st7735.c \
|
||||
Core/Hardware/KT0915/kt0915.c \
|
||||
Core/Hardware/SWI2C/i2c_sw.c \
|
||||
Core/App/Graphic/monoimg.c \
|
||||
Core/App/Graphic/ui_menu.c \
|
||||
Core/App/Graphic/ui_utils.c \
|
||||
Core/App/Graphic/ui.c \
|
||||
Core/App/Graphic/bmfont.c \
|
||||
Core/App/Graphic/asciifont.c \
|
||||
@ -155,7 +157,7 @@ C_INCLUDES = \
|
||||
# compile gcc flags
|
||||
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
|
||||
|
||||
CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
|
||||
CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections -fstack-usage
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -g -gdwarf-2
|
||||
@ -221,7 +223,10 @@ clean:
|
||||
# flash
|
||||
#######################################
|
||||
flash:
|
||||
-JLinkExe cmd.jexe
|
||||
-JLinkExe flash.jexe
|
||||
|
||||
reset:
|
||||
-JLinkExe reset.jexe
|
||||
|
||||
#######################################
|
||||
# dependencies
|
||||
|
7
reset.jexe
Normal file
7
reset.jexe
Normal file
@ -0,0 +1,7 @@
|
||||
Device STM32G030C8
|
||||
SelectInterface SWD
|
||||
Speed auto
|
||||
Connect
|
||||
Reset
|
||||
Go
|
||||
EXit
|
Loading…
x
Reference in New Issue
Block a user