Working on Bitmaps

This commit is contained in:
Marvin 2025-08-27 14:42:05 +02:00
parent edbb125d50
commit 30dbab7342
6 changed files with 231 additions and 52 deletions

View File

@ -15,6 +15,7 @@
"string": "c",
"string_view": "c",
"buttons.h": "c",
"master.h": "c"
"master.h": "c",
"device.h": "c"
}
}

View File

@ -26,7 +26,9 @@ Bei start:
source zephyrproject/.venv/bin/activate
cd zephyrproject/EdSaGfmvA/
west build -b <board> -- -DEXTRA_CONF_FILE=conf_EPD.conf
west build -p always -b nucleo_wl55jc . -DEXTRA_CONF_FILE=conf_EPD.conf
west build -p always -b nucleo_wl55jc . -DEXTRA_CONF_FILE=conf_OLED.conf
west flash
minicom:

View File

@ -4,16 +4,16 @@
#include <stdint.h>
// ## 1. Konstanten ##
#define CHAR_WIDTH 32
#define CHAR_HEIGHT 16
#define CHAR_BYTES 64
#define FONT_WIDTH 16
#define FONT_HEIGHT 32
#define FONT_WIDTH_BYTES 2
// ## 2. Globale Variablen (mit "extern") ##
extern const uint8_t fullscreen_allArray_LEN;
extern const unsigned char* fullscreen_allArray[36];
//extern const uint8_t fullscreen_allArray_LEN;
//extern const unsigned char* fullscreen_allArray[36];
// ## 3. Funktions-Prototypen ##
static inline void set_pixel_horizontal(uint8_t* fb, int x, int y);
void create_fullscreen_char(char c, uint8_t* fb, uint8_t scale);
//void create_char(char character, uint8_t* framebuffer, uint8_t scale);
void draw_char(char character, uint8_t* framebuffer, int fb_width, int fb_height, uint8_t scale);
#endif // FONT_MINI_H

View File

@ -7,6 +7,7 @@
#include "epaper/epaper.h"
#include "font.h"
#include "epaper/font_mini.h"
//#include "font.h"
@ -189,13 +190,22 @@ void epd_init(void){
void epd_update(void) {
epd_write_command(0x22);
epd_write_data(0xFF);
epd_write_data(0xC7); //war FF
epd_write_command(0x20);
epd_readbusy();
}
// Beispiel für das Senden eines Bildes
void epd_whitescreen_all(const uint8_t *datas) {
// sicheres Set vor 0x24
epd_write_command(0x11); epd_write_data(0x01); // zeilenweise
epd_write_command(0x44); epd_write_data(0x00); epd_write_data(0x1F); // X: 0..31 (Bytes)
epd_write_command(0x45); epd_write_data(0x00); epd_write_data(0x00);
epd_write_data(0x79); epd_write_data(0x00); // Y: 0..121 (Zeilen)
epd_write_command(0x4E); epd_write_data(0x00); // X-Zähler = 0
epd_write_command(0x4F); epd_write_data(0x00); epd_write_data(0x00); // Y-Zähler = 0
EPD_W21_CS_0; // <-- CS hier aktivieren (LOW)
epd_write_command(0x24); // Command: write RAM for black/white image
@ -246,6 +256,15 @@ void epd_whitescreen_white(void) {
void epd_clear(void) {
printk("🧹 Clearing display...\n");
// sicheres Set vor 0x24
epd_write_command(0x11); epd_write_data(0x01); // zeilenweise
epd_write_command(0x44); epd_write_data(0x00); epd_write_data(0x1F); // X: 0..31 (Bytes)
epd_write_command(0x45); epd_write_data(0x00); epd_write_data(0x00);
epd_write_data(0x79); epd_write_data(0x00); // Y: 0..121 (Zeilen)
epd_write_command(0x4E); epd_write_data(0x00); // X-Zähler = 0
epd_write_command(0x4F); epd_write_data(0x00); epd_write_data(0x00); // Y-Zähler = 0
// RAM für das Bild mit "Weiß" füllen
EPD_W21_CS_0;
@ -266,8 +285,16 @@ void epd_clear(void) {
void epd_draw_something(char toDraw) {
epd_clear();
create_fullscreen_char('K', epaper_framebuffer, 7);
//epd_whitescreen_all(HALLO);
//k_msleep(2000);
draw_char('K', epaper_framebuffer, 256, HEIGHT, 17);
epd_whitescreen_all(epaper_framebuffer);
// Muster in den Display-RAM schreiben
/*printk("Schreibe Bild in den Display-RAM...\n");
EPD_W21_CS_0;

View File

@ -1,14 +1,15 @@
#include <stdint.h>
/*#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "epaper/font_mini.h"
// '0', 32x16px
const unsigned char fullscreen_hor_0 [] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x01, 0xff,
0xff, 0x80, 0x01, 0xff, 0xff, 0x00, 0x00, 0xff, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe, 0x7f,
0xff, 0x00, 0x00, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
0xff, 0xff, 0xff, 0xff, 0xc0, 0x01, 0x80, 0x01, 0x87, 0xf9, 0x8f, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9,
0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x01, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9,
0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8,
0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff
};
// '1', 32x16px
const unsigned char fullscreen_hor_1 [] = {
@ -75,10 +76,10 @@ const unsigned char fullscreen_hor_9 [] = {
};
// 'A', 32x16px
const unsigned char fullscreen_hor_A [] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x01, 0xff,
0xfe, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x3e, 0x7f, 0xff, 0xfe, 0x3e, 0x7f,
0xfe, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
0xff, 0xff, 0xff, 0xff, 0xc0, 0x01, 0x80, 0x01, 0x87, 0xf9, 0x8f, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9,
0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x01, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9,
0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8,
0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff
};
// 'B', 32x16px
const unsigned char fullscreen_hor_B [] = {
@ -256,6 +257,19 @@ const unsigned char fullscreen_hor_Z [] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
// Test-Bitmap: Ein 16x32 Pixel großer Rahmen
const unsigned char test_bitmap[64] = {
// Oberste Zeile (alle Pixel an)
0xFF, 0xFF,
// 30x die Mitte (nur erster und letzter Pixel an)
0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
// Unterste Zeile (alle Pixel an)
0xFF, 0xFF
};
// Array of all bitmaps for convenience. (Total bytes used to store images in = 2880)
const uint8_t fullscreen_hor_allArray_LEN = 36;
const unsigned char* fullscreen_hor_allArray[36] = {
@ -297,44 +311,179 @@ const unsigned char* fullscreen_hor_allArray[36] = {
fullscreen_hor_Z
};
// --- FINALE set_pixel Funktion (für HORIZONTALEN Framebuffer) ---
// Schreibt einen schwarzen Pixel (setzt Bit auf 0) in den Buffer.
static void set_pixel_final(uint8_t* framebuffer, int x, int y) {
// Die Breite des E-Paper-Buffers in Bytes ist 32 (256 Pixel / 8)
int framebuffer_width_bytes = 32;
// Dieses Set an Funktionen arbeitet nur mit HORIZONTALEN Daten
static inline void set_pixel_horizontal(uint8_t* fb, int x, int y) {
if (x < 0 || x >= 250 || y < 0 || y >= 122) return;
int byte_index = y * 32 + (x >> 3); // 32 Bytes pro Zeile!
uint8_t bit = 0x80 >> (x & 7); // MSB-first
fb[byte_index] &= (uint8_t)~bit; // schwarz (Bit löschen)
// Sicherheitsabfrage
if (x < 0 || x >= 256 || y < 0 || y >= 122) {
return;
}
void create_fullscreen_char(char c, uint8_t* fb, uint8_t scale) {
// Hintergrund weiß
memset(fb, 0xFF, 3904);
// Korrekte Formel für einen horizontalen Framebuffer
int byte_index = y * framebuffer_width_bytes + (x / 8);
uint8_t bit_mask = 0x80 >> (x % 8); // MSB-first
// Index des Zeichens
int idx = -1;
if (c >= '0' && c <= '9') idx = c - '0';
else if (c >= 'A' && c <= 'Z') idx = (c - 'A') + 10;
if (idx < 0 || idx >= fullscreen_hor_allArray_LEN) return;
// Bit löschen für Schwarz auf weißem Grund
framebuffer[byte_index] &= ~bit_mask;
}
const uint8_t* bmp = fullscreen_hor_allArray[idx];
// Zentrieren
int w = CHAR_WIDTH * scale;
int h = CHAR_HEIGHT * scale;
int start_x = (250 - w) / 2;
int start_y = (122 - h) / 2;
// --- FINALE create_fullscreen_char Funktion ---
// Liest einen horizontalen 16x32 Font und skaliert ihn auf den Framebuffer.
void create_char(char character, uint8_t* framebuffer, uint8_t scale) {
// 1. Hintergrund auf Weiß (0xFF) füllen
memset(framebuffer, 0xFF, 3904);
// Zeichnen image2cpp: Horizontal, 1bpp, MSB-first, **1 = schwarz**
for (int y = 0; y < CHAR_HEIGHT; y++) {
for (int x = 0; x < CHAR_WIDTH; x++) {
int glyph_byte = y * (CHAR_WIDTH/8) + (x >> 3); // 4 Bytes pro Glyphenzeile
uint8_t mask = 0x80 >> (x & 7);
if (bmp[glyph_byte] & mask) { // 1 = Pixel gesetzt (schwarz)
// 2. Zeichenindex finden
int index = -1;
if (character >= '0' && character <= '9') {
index = character - '0';
} else if (character >= 'A' && character <= 'Z') {
index = (character - 'A') + 10;
}
if (index < 0 || index >= fullscreen_hor_allArray_LEN) return;
const uint8_t* font_bitmap = fullscreen_hor_allArray[index];
// 3. Zentrierung berechnen
int scaled_width = FONT_WIDTH * scale;
int scaled_height = FONT_HEIGHT * scale;
int start_x = (256 - scaled_width) / 2;
int start_y = (122 - scaled_height) / 2;
// 4. Pixel für Pixel durch den kleinen FONT iterieren
for (int font_y = 0; font_y < FONT_HEIGHT; font_y++) {
for (int font_x = 0; font_x < FONT_WIDTH; font_x++) {
// Pixel aus dem HORIZONTALEN Font-Array lesen
int font_byte_index = (font_y * FONT_WIDTH_BYTES) + (font_x / 8);
uint8_t font_bit_mask = 0x80 >> (font_x % 8);
// Wenn der Pixel im Font gesetzt ist...
if (font_bitmap[font_byte_index] & font_bit_mask) {
// ...zeichne einen skalierten Block an die Ziel-Position
for (int sy = 0; sy < scale; sy++) {
for (int sx = 0; sx < scale; sx++) {
set_pixel_horizontal(fb, start_x + x*scale + sx,
start_y + y*scale + sy);
set_pixel_final(framebuffer, start_x + (font_x * scale) + sx, start_y + (font_y * scale) + sy);
}
}
}
}
}
}
*/
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "epaper/font_mini.h" // Passe diesen Pfad ggf. an
// =================================================================================
// STANDARD 5x7 ASCII FONT (Horizontal, MSB-first)
// =================================================================================
const unsigned char font5x7[] = {
0x00, 0x00, 0x00, 0x00, 0x00, // sp
0x00, 0x00, 0x5F, 0x00, 0x00, // !
0x00, 0x07, 0x00, 0x07, 0x00, // "
0x14, 0x7F, 0x14, 0x7F, 0x14, // #
0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
0x23, 0x13, 0x08, 0x64, 0x62, // %
0x36, 0x49, 0x55, 0x22, 0x50, // &
0x00, 0x05, 0x03, 0x00, 0x00, // '
0x00, 0x1C, 0x22, 0x41, 0x00, // (
0x00, 0x41, 0x22, 0x1C, 0x00, // )
0x08, 0x2A, 0x1C, 0x2A, 0x08, // *
0x08, 0x08, 0x3E, 0x08, 0x08, // +
0x00, 0x50, 0x30, 0x00, 0x00, // ,
0x08, 0x08, 0x08, 0x08, 0x08, // -
0x00, 0x60, 0x60, 0x00, 0x00, // .
0x20, 0x10, 0x08, 0x04, 0x02, // /
0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
0x00, 0x42, 0x7F, 0x40, 0x00, // 1
0x42, 0x61, 0x51, 0x49, 0x46, // 2
0x21, 0x41, 0x45, 0x4B, 0x31, // 3
0x18, 0x14, 0x12, 0x7F, 0x10, // 4
0x27, 0x45, 0x45, 0x45, 0x39, // 5
0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
0x01, 0x71, 0x09, 0x05, 0x03, // 7
0x36, 0x49, 0x49, 0x49, 0x36, // 8
0x06, 0x49, 0x49, 0x29, 0x1E, // 9
0x00, 0x36, 0x36, 0x00, 0x00, // :
0x00, 0x56, 0x36, 0x00, 0x00, // ;
0x00, 0x08, 0x14, 0x22, 0x41, // <
0x14, 0x14, 0x14, 0x14, 0x14, // =
0x41, 0x22, 0x14, 0x08, 0x00, // >
0x02, 0x01, 0x51, 0x09, 0x06, // ?
0x32, 0x49, 0x79, 0x41, 0x3E, // @
0x7E, 0x11, 0x11, 0x11, 0x7E, // A
0x7F, 0x49, 0x49, 0x49, 0x36, // B
0x3E, 0x41, 0x41, 0x41, 0x22, // C
0x7F, 0x41, 0x41, 0x22, 0x1C, // D
0x7F, 0x49, 0x49, 0x49, 0x41, // E
0x7F, 0x09, 0x09, 0x01, 0x01, // F
0x3E, 0x41, 0x41, 0x51, 0x32, // G
0x7F, 0x08, 0x08, 0x08, 0x7F, // H
0x00, 0x41, 0x7F, 0x41, 0x00, // I
0x20, 0x40, 0x41, 0x3F, 0x01, // J
0x7F, 0x08, 0x14, 0x22, 0x41, // K
0x7F, 0x40, 0x40, 0x40, 0x40, // L
0x7F, 0x02, 0x04, 0x02, 0x7F, // M
0x7F, 0x04, 0x08, 0x10, 0x7F, // N
0x3E, 0x41, 0x41, 0x41, 0x3E, // O
0x7F, 0x09, 0x09, 0x09, 0x06, // P
0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
0x7F, 0x09, 0x19, 0x29, 0x46, // R
0x46, 0x49, 0x49, 0x49, 0x31, // S
0x01, 0x01, 0x7F, 0x01, 0x01, // T
0x3F, 0x40, 0x40, 0x40, 0x3F, // U
0x1F, 0x20, 0x40, 0x20, 0x1F, // V
0x3F, 0x40, 0x38, 0x40, 0x3F, // W
0x63, 0x14, 0x08, 0x14, 0x63, // X
0x03, 0x04, 0x78, 0x04, 0x03, // Y
0x61, 0x51, 0x49, 0x45, 0x43, // Z
};
// =================================================================================
// FINALE, VEREINFACHTE ZEICHENFUNKTION
// =================================================================================
void draw_char(char character, uint8_t* framebuffer, int fb_width, int fb_height, uint8_t scale) {
// Hintergrund auf Weiß (0xFF) füllen
memset(framebuffer, 0xFF, (fb_width / 8) * fb_height);
// Zeichen-Index finden (nur druckbare ASCII-Zeichen)
if (character < ' ' || character > 'z') {
character = '?'; // Fallback-Zeichen
}
const uint8_t* font_ptr = font5x7 + (character - ' ') * 5;
int scaled_width = 5 * scale;
int scaled_height = 7 * scale;
int start_x = (fb_width - scaled_width) / 2;
int start_y = (fb_height - scaled_height) / 2;
// Zeichen Pixel für Pixel malen
for (int y = 0; y < 7; y++) { // Höhe des Fonts ist 7
for (int x = 0; x < 5; x++) { // Breite des Fonts ist 5
// Pixel aus dem Font-Array lesen
// Jede Spalte ist 1 Byte, Bit 0 ist oben.
if ((font_ptr[x] >> y) & 0x01) {
// Skalierten Block an die Ziel-Position malen
for (int sy = 0; sy < scale; sy++) {
for (int sx = 0; sx < scale; sx++) {
int target_x = start_x + (x * scale) + sx;
int target_y = start_y + (y * scale) + sy;
// Pixel in den HORIZONTALEN Framebuffer schreiben
if (target_x >= 0 && target_x < fb_width && target_y >= 0 && target_y < fb_height) {
int byte_index = (target_y * (fb_width / 8)) + (target_x / 8);
uint8_t bit_mask = 0x80 >> (target_x % 8);
framebuffer[byte_index] &= ~bit_mask; // Bit löschen für Schwarz
}
}
}
}

View File

@ -51,7 +51,7 @@ void lora_receive_cb(const struct device *dev,
int enable_lora_receive(void)
{
// Empfang sicher neu starten
lora_recv_async(lora_dev, NULL);
lora_recv_async(lora_dev, NULL, NULL);
memset(&samples, 0, sizeof(samples));
int ret = lora_config(lora_dev, &config);
@ -60,7 +60,7 @@ int enable_lora_receive(void)
return ret;
}
ret = lora_recv_async(lora_dev, lora_receive_cb);
ret = lora_recv_async(lora_dev, lora_receive_cb, NULL);
if (ret != 0) {
printk("Empfang konnte nicht aktiviert werden: %d\n", ret);
return ret;
@ -72,7 +72,7 @@ int enable_lora_receive(void)
int disable_lora_receive(void)
{
int ret = lora_recv_async(lora_dev, NULL);
int ret = lora_recv_async(lora_dev, NULL, NULL);
if (ret != 0) {
printk("Empfang konnte nicht deaktiviert werden: %d\n", ret);
return ret;
@ -103,7 +103,7 @@ void lora_thread(void *p1, void *p2, void *p3)
void lora_init(void)
{
lora_recv_async(lora_dev, NULL); // sicher deaktivieren
lora_recv_async(lora_dev, NULL, NULL); // sicher deaktivieren
k_thread_create(&lora_thread_data, lora_stack_area, STACK_SIZE,
lora_thread, NULL, NULL, NULL,
PRIORITY, 0, K_NO_WAIT);