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": "c",
"string_view": "c", "string_view": "c",
"buttons.h": "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 source zephyrproject/.venv/bin/activate
cd zephyrproject/EdSaGfmvA/ 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 west flash
minicom: minicom:

View File

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

View File

@ -7,6 +7,7 @@
#include "epaper/epaper.h" #include "epaper/epaper.h"
#include "font.h"
#include "epaper/font_mini.h" #include "epaper/font_mini.h"
//#include "font.h" //#include "font.h"
@ -189,13 +190,22 @@ void epd_init(void){
void epd_update(void) { void epd_update(void) {
epd_write_command(0x22); epd_write_command(0x22);
epd_write_data(0xFF); epd_write_data(0xC7); //war FF
epd_write_command(0x20); epd_write_command(0x20);
epd_readbusy(); epd_readbusy();
} }
// Beispiel für das Senden eines Bildes // Beispiel für das Senden eines Bildes
void epd_whitescreen_all(const uint8_t *datas) { 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_W21_CS_0; // <-- CS hier aktivieren (LOW)
epd_write_command(0x24); // Command: write RAM for black/white image epd_write_command(0x24); // Command: write RAM for black/white image
@ -246,6 +256,15 @@ void epd_whitescreen_white(void) {
void epd_clear(void) { void epd_clear(void) {
printk("🧹 Clearing display...\n"); 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 // RAM für das Bild mit "Weiß" füllen
EPD_W21_CS_0; EPD_W21_CS_0;
@ -266,8 +285,16 @@ void epd_clear(void) {
void epd_draw_something(char toDraw) { void epd_draw_something(char toDraw) {
epd_clear(); 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); epd_whitescreen_all(epaper_framebuffer);
// Muster in den Display-RAM schreiben // Muster in den Display-RAM schreiben
/*printk("Schreibe Bild in den Display-RAM...\n"); /*printk("Schreibe Bild in den Display-RAM...\n");
EPD_W21_CS_0; EPD_W21_CS_0;

View File

@ -1,14 +1,15 @@
#include <stdint.h> /*#include <stdint.h>
#include <string.h> #include <string.h>
#include <stdbool.h>
#include "epaper/font_mini.h" #include "epaper/font_mini.h"
// '0', 32x16px // '0', 32x16px
const unsigned char fullscreen_hor_0 [] = { const unsigned char fullscreen_hor_0 [] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x01, 0x80, 0x01, 0x87, 0xf9, 0x8f, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9,
0xff, 0x80, 0x01, 0xff, 0xff, 0x00, 0x00, 0xff, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe, 0x7f, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x01, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9,
0xff, 0x00, 0x00, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff
}; };
// '1', 32x16px // '1', 32x16px
const unsigned char fullscreen_hor_1 [] = { const unsigned char fullscreen_hor_1 [] = {
@ -75,10 +76,10 @@ const unsigned char fullscreen_hor_9 [] = {
}; };
// 'A', 32x16px // 'A', 32x16px
const unsigned char fullscreen_hor_A [] = { const unsigned char fullscreen_hor_A [] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x01, 0x80, 0x01, 0x87, 0xf9, 0x8f, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9,
0xfe, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x3e, 0x7f, 0xff, 0xfe, 0x3e, 0x7f, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x01, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9,
0xfe, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf9, 0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8, 0xcf, 0xf8, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff
}; };
// 'B', 32x16px // 'B', 32x16px
const unsigned char fullscreen_hor_B [] = { 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 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) // Array of all bitmaps for convenience. (Total bytes used to store images in = 2880)
const uint8_t fullscreen_hor_allArray_LEN = 36; const uint8_t fullscreen_hor_allArray_LEN = 36;
const unsigned char* fullscreen_hor_allArray[36] = { const unsigned char* fullscreen_hor_allArray[36] = {
@ -297,44 +311,179 @@ const unsigned char* fullscreen_hor_allArray[36] = {
fullscreen_hor_Z 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 // Sicherheitsabfrage
if (x < 0 || x >= 256 || y < 0 || y >= 122) {
static inline void set_pixel_horizontal(uint8_t* fb, int x, int y) { return;
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)
} }
void create_fullscreen_char(char c, uint8_t* fb, uint8_t scale) { // Korrekte Formel für einen horizontalen Framebuffer
// Hintergrund weiß int byte_index = y * framebuffer_width_bytes + (x / 8);
memset(fb, 0xFF, 3904); uint8_t bit_mask = 0x80 >> (x % 8); // MSB-first
// Index des Zeichens // Bit löschen für Schwarz auf weißem Grund
int idx = -1; framebuffer[byte_index] &= ~bit_mask;
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;
const uint8_t* bmp = fullscreen_hor_allArray[idx];
// Zentrieren // --- FINALE create_fullscreen_char Funktion ---
int w = CHAR_WIDTH * scale; // Liest einen horizontalen 16x32 Font und skaliert ihn auf den Framebuffer.
int h = CHAR_HEIGHT * scale; void create_char(char character, uint8_t* framebuffer, uint8_t scale) {
int start_x = (250 - w) / 2; // 1. Hintergrund auf Weiß (0xFF) füllen
int start_y = (122 - h) / 2; memset(framebuffer, 0xFF, 3904);
// Zeichnen image2cpp: Horizontal, 1bpp, MSB-first, **1 = schwarz** // 2. Zeichenindex finden
for (int y = 0; y < CHAR_HEIGHT; y++) { int index = -1;
for (int x = 0; x < CHAR_WIDTH; x++) { if (character >= '0' && character <= '9') {
int glyph_byte = y * (CHAR_WIDTH/8) + (x >> 3); // 4 Bytes pro Glyphenzeile index = character - '0';
uint8_t mask = 0x80 >> (x & 7); } else if (character >= 'A' && character <= 'Z') {
if (bmp[glyph_byte] & mask) { // 1 = Pixel gesetzt (schwarz) 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 sy = 0; sy < scale; sy++) {
for (int sx = 0; sx < scale; sx++) { for (int sx = 0; sx < scale; sx++) {
set_pixel_horizontal(fb, start_x + x*scale + sx, set_pixel_final(framebuffer, start_x + (font_x * scale) + sx, start_y + (font_y * scale) + sy);
start_y + 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) int enable_lora_receive(void)
{ {
// Empfang sicher neu starten // Empfang sicher neu starten
lora_recv_async(lora_dev, NULL); lora_recv_async(lora_dev, NULL, NULL);
memset(&samples, 0, sizeof(samples)); memset(&samples, 0, sizeof(samples));
int ret = lora_config(lora_dev, &config); int ret = lora_config(lora_dev, &config);
@ -60,7 +60,7 @@ int enable_lora_receive(void)
return ret; return ret;
} }
ret = lora_recv_async(lora_dev, lora_receive_cb); ret = lora_recv_async(lora_dev, lora_receive_cb, NULL);
if (ret != 0) { if (ret != 0) {
printk("Empfang konnte nicht aktiviert werden: %d\n", ret); printk("Empfang konnte nicht aktiviert werden: %d\n", ret);
return ret; return ret;
@ -72,7 +72,7 @@ int enable_lora_receive(void)
int disable_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) { if (ret != 0) {
printk("Empfang konnte nicht deaktiviert werden: %d\n", ret); printk("Empfang konnte nicht deaktiviert werden: %d\n", ret);
return ret; return ret;
@ -103,7 +103,7 @@ void lora_thread(void *p1, void *p2, void *p3)
void lora_init(void) 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, k_thread_create(&lora_thread_data, lora_stack_area, STACK_SIZE,
lora_thread, NULL, NULL, NULL, lora_thread, NULL, NULL, NULL,
PRIORITY, 0, K_NO_WAIT); PRIORITY, 0, K_NO_WAIT);