diff --git a/.vscode/settings.json b/.vscode/settings.json index 4c47b40..52540ef 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,6 +15,7 @@ "string": "c", "string_view": "c", "buttons.h": "c", - "master.h": "c" + "master.h": "c", + "device.h": "c" } } \ No newline at end of file diff --git a/README.rst b/README.rst index cbba0ed..2185952 100644 --- a/README.rst +++ b/README.rst @@ -26,7 +26,9 @@ Bei start: source zephyrproject/.venv/bin/activate cd zephyrproject/EdSaGfmvA/ -west build -b -- -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: diff --git a/include/epaper/font_mini.h b/include/epaper/font_mini.h index 66cd19c..5a101e2 100644 --- a/include/epaper/font_mini.h +++ b/include/epaper/font_mini.h @@ -4,16 +4,16 @@ #include // ## 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 \ No newline at end of file diff --git a/src/epaper/epaper.c b/src/epaper/epaper.c index ce4be00..98c838e 100644 --- a/src/epaper/epaper.c +++ b/src/epaper/epaper.c @@ -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; diff --git a/src/epaper/font_mini.c b/src/epaper/font_mini.c index bcc5633..ac31a17 100644 --- a/src/epaper/font_mini.c +++ b/src/epaper/font_mini.c @@ -1,14 +1,15 @@ -#include +/*#include #include +#include #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 + // Sicherheitsabfrage + if (x < 0 || x >= 256 || y < 0 || y >= 122) { + return; + } -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) + // 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 + + // Bit löschen für Schwarz auf weißem Grund + framebuffer[byte_index] &= ~bit_mask; } -void create_fullscreen_char(char c, uint8_t* fb, uint8_t scale) { - // Hintergrund weiß - memset(fb, 0xFF, 3904); - // 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; +// --- 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); - const uint8_t* bmp = fullscreen_hor_allArray[idx]; + // 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; - // Zentrieren - int w = CHAR_WIDTH * scale; - int h = CHAR_HEIGHT * scale; - int start_x = (250 - w) / 2; - int start_y = (122 - h) / 2; + const uint8_t* font_bitmap = fullscreen_hor_allArray[index]; - // 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) + // 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 +#include +#include +#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 + } } } } diff --git a/src/lora/lora.c b/src/lora/lora.c index 109308c..6db7c22 100644 --- a/src/lora/lora.c +++ b/src/lora/lora.c @@ -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);