WIP, ui_menu

This commit is contained in:
Sheikah 2023-02-05 00:52:46 +08:00
parent a6d091a7e5
commit 30ece44ea4
20 changed files with 443 additions and 77 deletions

View File

@ -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"
}
}

View File

@ -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) {

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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
View 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;
}
}
}

View 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);

View 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);
}

View 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);

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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() {

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -1,3 +0,0 @@
#!/bin/bash
JLinkExe cmd.jexe

7
reset.jexe Normal file
View File

@ -0,0 +1,7 @@
Device STM32G030C8
SelectInterface SWD
Speed auto
Connect
Reset
Go
EXit