rotate framebuffer

fake-chip
Ondřej Hruška 2 years ago
parent e5a6bff29c
commit 2521cd75c7
  1. 10
      Core/Inc/app.h
  2. 47
      Core/Src/app_main.c
  3. 94
      Core/Src/app_oled.c
  4. 1
      Core/Src/freertos.c
  5. 3
      Lib/ufb/Inc/ufb/fb_7seg.h
  6. 4
      Lib/ufb/Inc/ufb/framebuffer_config.h
  7. 41
      Lib/ufb/Src/fb_7seg.c

@ -1,10 +0,0 @@
/**
* Application main task
*/
#ifndef APP_H
#define APP_H
void app_main_task(void *argument);
#endif //APP_H

@ -3,16 +3,17 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <math.h>
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "main.h" #include "main.h"
#include "app.h"
#include "ufb/framebuffer.h" #include "ufb/framebuffer.h"
#include "iwdg.h" #include "iwdg.h"
#include "app_oled.h" #include "app_oled.h"
#include "ufb/fb_text.h" #include "ufb/fb_text.h"
#include "ufb/fb_7seg.h"
#include "app_temp.h" #include "app_temp.h"
#include "app_knob.h" #include "app_knob.h"
#include "app_buzzer.h" #include "app_buzzer.h"
@ -32,19 +33,51 @@ static void redraw_display() {
char tmp[100]; char tmp[100];
sprintf(tmp, "Mereni: %d°C", (int) s_app.oven_temp); sprintf(tmp, "T=%d°C", (int) s_app.oven_temp);
fb_text(10, 5, tmp, 0, 1); fb_text(3, 3, tmp, FONT_5X7, 1);
sprintf(tmp, " Cil: %d°C", s_app.set_temp); sprintf(tmp, "Cil=%d°C", s_app.set_temp);
fb_text(10, 20, tmp, 0, 1); fb_text(3, 11, tmp, FONT_5X7, 1);
sprintf(tmp, " Stav: %s", s_app.run ? "ZAP" : "VYP"); sprintf(tmp, "Stav=%s", s_app.run ? "ZAP" : "VYP");
fb_text(10, 35, tmp, 0, 1); fb_text(3, 19, tmp, FONT_5X7, 1);
if (s_app.run) { if (s_app.run) {
fb_frame(0, 0, FBW, FBH, 2, 1); 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(); fb_blit();
} }

@ -3,6 +3,7 @@
// //
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "ufb/framebuffer.h" #include "ufb/framebuffer.h"
#include "gpio.h" #include "gpio.h"
@ -12,27 +13,32 @@
#define SSD1309_HEIGHT 64 #define SSD1309_HEIGHT 64
static inline void cs_select() { static inline void cs_select()
{
asm volatile("nop \n nop \n nop"); asm volatile("nop \n nop \n nop");
HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, 0); // Active low HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, 0); // Active low
asm volatile("nop \n nop \n nop"); asm volatile("nop \n nop \n nop");
} }
static inline void cs_deselect() { static inline void cs_deselect()
{
asm volatile("nop \n nop \n nop"); asm volatile("nop \n nop \n nop");
HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, 1); HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, 1);
asm volatile("nop \n nop \n nop"); 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); 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); 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]; uint8_t buf[2];
buf[0] = cmd; buf[0] = cmd;
buf[1] = arg; buf[1] = arg;
@ -42,14 +48,16 @@ void oled_command16(uint8_t cmd, uint8_t arg) {
cs_deselect(); cs_deselect();
} }
void oled_command(uint8_t cmd) { void oled_command(uint8_t cmd)
{
dc_command(); dc_command();
cs_select(); cs_select();
HAL_SPI_Transmit(&OLED_HSPI, &cmd, 1, 1000); HAL_SPI_Transmit(&OLED_HSPI, &cmd, 1, 1000);
cs_deselect(); cs_deselect();
} }
void oled_reset() { void oled_reset()
{
// Issue a display reset // Issue a display reset
HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, 0); HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, 0);
HAL_Delay(1); HAL_Delay(1);
@ -57,7 +65,8 @@ void oled_reset() {
HAL_Delay(1); HAL_Delay(1);
} }
void oled_invert(bool invert) { void oled_invert(bool invert)
{
if (invert) { if (invert) {
oled_command(0xA6); oled_command(0xA6);
} else { } else {
@ -65,7 +74,8 @@ void oled_invert(bool invert) {
} }
} }
void oled_init() { void oled_init()
{
oled_reset(); oled_reset();
// simplified display init // simplified display init
@ -160,13 +170,75 @@ void oled_init() {
#endif #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(); dc_data();
cs_select(); cs_select();
HAL_SPI_Transmit(&OLED_HSPI, data, len, 1000); HAL_SPI_Transmit(&OLED_HSPI, data, len, 1000);
cs_deselect(); cs_deselect();
} }
void fb_blit() { void fb_blit()
{
#if 0
oled_data(fb, FB_LEN); 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
} }

@ -26,7 +26,6 @@
/* Private includes ----------------------------------------------------------*/ /* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */ /* USER CODE BEGIN Includes */
#include <stdio.h> #include <stdio.h>
#include "app.h"
/* USER CODE END Includes */ /* USER CODE END Includes */

@ -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 /// \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); 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 #endif //FB_7SEG_H

@ -2,7 +2,7 @@
#define FRAMEBUFFER_CONFIG_H #define FRAMEBUFFER_CONFIG_H
/* Tiny framebuffer - size of the big actual OLED */ /* Tiny framebuffer - size of the big actual OLED */
#define FBW 128 #define FBW 64
#define FBH 64 #define FBH 128
#endif /* FRAMEBUFFER_CONFIG_H */ #endif /* FRAMEBUFFER_CONFIG_H */

@ -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, th,
hi, bcolor ^ (bool) (mask & LT)); hi, bcolor ^ (bool) (mask & LT));
fb_rect(x + th + wi, fb_rect(x,
y + hi + th, y + hi + th * 2,
th, th,
hi, bcolor ^ (bool) (mask & LB)); 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); fb_rect(x, y + hi * 2 + th * 2, th, th, color);
return th; 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;
}
}
}

Loading…
Cancel
Save