From 2521cd75c7145b4b61d856b37fdc19a83458fcdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Tue, 7 Mar 2023 23:49:54 +0100 Subject: [PATCH] rotate framebuffer --- Core/Inc/app.h | 10 --- Core/Src/app_main.c | 47 +++++++++++--- Core/Src/app_oled.c | 94 ++++++++++++++++++++++++---- Core/Src/freertos.c | 1 - Lib/ufb/Inc/ufb/fb_7seg.h | 3 + Lib/ufb/Inc/ufb/framebuffer_config.h | 4 +- Lib/ufb/Src/fb_7seg.c | 41 +++++++++++- 7 files changed, 167 insertions(+), 33 deletions(-) delete mode 100644 Core/Inc/app.h diff --git a/Core/Inc/app.h b/Core/Inc/app.h deleted file mode 100644 index 5f2eef6..0000000 --- a/Core/Inc/app.h +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Application main task - */ - -#ifndef APP_H -#define APP_H - -void app_main_task(void *argument); - -#endif //APP_H diff --git a/Core/Src/app_main.c b/Core/Src/app_main.c index 5b70dd2..8c3dc6e 100644 --- a/Core/Src/app_main.c +++ b/Core/Src/app_main.c @@ -3,16 +3,17 @@ */ #include +#include #include "FreeRTOS.h" #include "task.h" #include "main.h" -#include "app.h" #include "ufb/framebuffer.h" #include "iwdg.h" #include "app_oled.h" #include "ufb/fb_text.h" +#include "ufb/fb_7seg.h" #include "app_temp.h" #include "app_knob.h" #include "app_buzzer.h" @@ -32,19 +33,51 @@ static void redraw_display() { char tmp[100]; - sprintf(tmp, "Mereni: %d°C", (int) s_app.oven_temp); - fb_text(10, 5, tmp, 0, 1); + sprintf(tmp, "T=%d°C", (int) s_app.oven_temp); + fb_text(3, 3, tmp, FONT_5X7, 1); - sprintf(tmp, " Cil: %d°C", s_app.set_temp); - fb_text(10, 20, tmp, 0, 1); + sprintf(tmp, "Cil=%d°C", s_app.set_temp); + fb_text(3, 11, tmp, FONT_5X7, 1); - sprintf(tmp, " Stav: %s", s_app.run ? "ZAP" : "VYP"); - fb_text(10, 35, tmp, 0, 1); + sprintf(tmp, "Stav=%s", s_app.run ? "ZAP" : "VYP"); + fb_text(3, 19, tmp, FONT_5X7, 1); if (s_app.run) { fb_frame(0, 0, FBW, FBH, 2, 1); } + // some funny effects to showcase responsiveness and circle drawing + + fb_circle(FBW / 2, 70, 18, 1, 1); + + for (int i = 0; i < 6; i++) { + float x = FBW / 2; + float y = 70; + + int ii = i; + + float angle = (float) ii * (M_PI / 3.0) - s_app.wheel_normed * (M_PI / 24); + + x = x + sinf(angle) * 10; + y = y + cosf(angle) * 10; + + fb_circle((fbpos_t) x, (fbpos_t) y, 4, i==0?4:1, 1); + } + + fb_text(0, s_app.wheel_normed, ":3 :3", FONT_4X5, 1); + + fb_7seg_number( + 2, FBH - 20, + 10, 16, + 2, // th + 2, // spacing + 1, // color + s_app.wheel, + 4, // places + 2);// decimals + + + fb_blit(); } diff --git a/Core/Src/app_oled.c b/Core/Src/app_oled.c index 8f61ffc..2a37fb6 100644 --- a/Core/Src/app_oled.c +++ b/Core/Src/app_oled.c @@ -3,6 +3,7 @@ // #include +#include #include "ufb/framebuffer.h" #include "gpio.h" @@ -12,27 +13,32 @@ #define SSD1309_HEIGHT 64 -static inline void cs_select() { +static inline void cs_select() +{ asm volatile("nop \n nop \n nop"); HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, 0); // Active low asm volatile("nop \n nop \n nop"); } -static inline void cs_deselect() { +static inline void cs_deselect() +{ asm volatile("nop \n nop \n nop"); HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, 1); asm volatile("nop \n nop \n nop"); } -static inline void dc_command() { +static inline void dc_command() +{ HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, 0); } -static inline void dc_data() { +static inline void dc_data() +{ HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, 1); } -void oled_command16(uint8_t cmd, uint8_t arg) { +void oled_command16(uint8_t cmd, uint8_t arg) +{ uint8_t buf[2]; buf[0] = cmd; buf[1] = arg; @@ -42,14 +48,16 @@ void oled_command16(uint8_t cmd, uint8_t arg) { cs_deselect(); } -void oled_command(uint8_t cmd) { +void oled_command(uint8_t cmd) +{ dc_command(); cs_select(); HAL_SPI_Transmit(&OLED_HSPI, &cmd, 1, 1000); cs_deselect(); } -void oled_reset() { +void oled_reset() +{ // Issue a display reset HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, 0); HAL_Delay(1); @@ -57,7 +65,8 @@ void oled_reset() { HAL_Delay(1); } -void oled_invert(bool invert) { +void oled_invert(bool invert) +{ if (invert) { oled_command(0xA6); } else { @@ -65,7 +74,8 @@ void oled_invert(bool invert) { } } -void oled_init() { +void oled_init() +{ oled_reset(); // simplified display init @@ -160,13 +170,75 @@ void oled_init() { #endif } -void oled_data(uint8_t *data, size_t len) { +static void transpose8_and_reverse(const uint8_t *a, uint8_t *b) +{ + uint32_t x, y, t; + + // Load the array and pack it into x and y. + + x = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]; + y = (a[4] << 24) | (a[5] << 16) | (a[6] << 8) | a[7]; + + t = (x ^ (x >> 7)) & 0x00AA00AA; + x = x ^ t ^ (t << 7); + t = (y ^ (y >> 7)) & 0x00AA00AA; + y = y ^ t ^ (t << 7); + + t = (x ^ (x >> 14)) & 0x0000CCCC; + x = x ^ t ^ (t << 14); + t = (y ^ (y >> 14)) & 0x0000CCCC; + y = y ^ t ^ (t << 14); + + t = (x & 0xF0F0F0F0) | ((y >> 4) & 0x0F0F0F0F); + y = ((x << 4) & 0xF0F0F0F0) | (y & 0x0F0F0F0F); + x = t; + +// a[0] = x >> 24; +// a[1] = x >> 16; +// a[2] = x >> 8; +// a[3] = x; +// a[4] = y >> 24; +// a[5] = y >> 16; +// a[6] = y >> 8; +// a[7] = y; + + b[7] = x >> 24; + b[6] = x >> 16; + b[5] = x >> 8; + b[4] = x; + b[3] = y >> 24; + b[2] = y >> 16; + b[1] = y >> 8; + b[0] = y; +} + +void oled_data(uint8_t *data, size_t len) +{ dc_data(); cs_select(); HAL_SPI_Transmit(&OLED_HSPI, data, len, 1000); cs_deselect(); } -void fb_blit() { +void fb_blit() +{ +#if 0 oled_data(fb, FB_LEN); +#else + dc_data(); + cs_select(); + + // 90deg + uint8_t buf[8]; + for (int j = FBW / 8 - 1; j >= 0; j--) { + for (int i = 0; i < FBH / 8; i++) { + // i, j are "square coords" (8x8) + transpose8_and_reverse(&fb[i * FBW + j * 8], buf); + HAL_SPI_Transmit(&OLED_HSPI, buf, 8, 100); + } + } + + cs_deselect(); + +#endif } diff --git a/Core/Src/freertos.c b/Core/Src/freertos.c index 1b2c942..dfbacd0 100644 --- a/Core/Src/freertos.c +++ b/Core/Src/freertos.c @@ -26,7 +26,6 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include -#include "app.h" /* USER CODE END Includes */ diff --git a/Lib/ufb/Inc/ufb/fb_7seg.h b/Lib/ufb/Inc/ufb/fb_7seg.h index e4ffe19..c90fd99 100644 --- a/Lib/ufb/Inc/ufb/fb_7seg.h +++ b/Lib/ufb/Inc/ufb/fb_7seg.h @@ -29,4 +29,7 @@ fbpos_t fb_7seg_dig(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, uint /// \return width taken fbpos_t fb_7seg_period(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, fbcolor_t color); + +void fb_7seg_number(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, fbpos_t spacing, fbcolor_t color, uint16_t num, uint8_t places, uint8_t decimals); + #endif //FB_7SEG_H diff --git a/Lib/ufb/Inc/ufb/framebuffer_config.h b/Lib/ufb/Inc/ufb/framebuffer_config.h index 3a240ad..30e9dfe 100644 --- a/Lib/ufb/Inc/ufb/framebuffer_config.h +++ b/Lib/ufb/Inc/ufb/framebuffer_config.h @@ -2,7 +2,7 @@ #define FRAMEBUFFER_CONFIG_H /* Tiny framebuffer - size of the big actual OLED */ -#define FBW 128 -#define FBH 64 +#define FBW 64 +#define FBH 128 #endif /* FRAMEBUFFER_CONFIG_H */ diff --git a/Lib/ufb/Src/fb_7seg.c b/Lib/ufb/Src/fb_7seg.c index 630a0bc..92abd3f 100644 --- a/Lib/ufb/Src/fb_7seg.c +++ b/Lib/ufb/Src/fb_7seg.c @@ -46,8 +46,8 @@ fbpos_t fb_7seg_dig(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, uint th, hi, bcolor ^ (bool) (mask & LT)); - fb_rect(x + th + wi, - y + hi + th, + fb_rect(x, + y + hi + th * 2, th, hi, bcolor ^ (bool) (mask & LB)); @@ -70,3 +70,40 @@ fbpos_t fb_7seg_period(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, f fb_rect(x, y + hi * 2 + th * 2, th, th, color); return th; } + +void fb_7seg_number(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, fbpos_t spacing, fbcolor_t color, uint16_t num, uint8_t places, uint8_t decimals) +{ + uint8_t digits[5] = {}; + uint8_t pos = 4; + while (num > 0) { + uint8_t res = num % 10; + num /= 10; + digits[pos] = res; + pos--; + } + + bool drawing = false; + for (uint8_t i = 5 - places; i < 5; i++) { + uint8_t d = digits[i]; + + if (i == 5 - decimals) { + fb_7seg_period(x, y, w, h, th, color); + x += th + spacing; + } + + if (!drawing && d == 0) { + if (i == 5 - decimals - 1) { + fb_7seg_dig(x, y, w, h, th, d, color); + x += w + spacing; + drawing = true; + } else { + fb_7seg_dig(x, y, w, h, th, 8, !color); // clear + x += w + spacing; + } + } else { + fb_7seg_dig(x, y, w, h, th, d, color); + x += w + spacing; + drawing = true; + } + } +}