Merging everything

This commit is contained in:
maroh94 2025-08-18 00:48:30 +02:00
parent de18d1a5c4
commit 5089614205
27 changed files with 4671 additions and 163 deletions

View File

@ -7,7 +7,6 @@
"font.h": "c",
"oled.h": "c",
"leds.h": "c",
"constandvars.h": "c",
"kernel.h": "c",
"lora.h": "c",
"spi.h": "c",

View File

@ -1,4 +1,11 @@
cmake_minimum_required(VERSION 3.20.0)
if(DEFINED EXTRA_CONF_FILE AND EXTRA_CONF_FILE MATCHES "EPD")
set(DTC_OVERLAY_FILE ${CMAKE_CURRENT_SOURCE_DIR}/boards/nucleo_wl55jc_epd.overlay)
elseif(DEFINED EXTRA_CONF_FILE AND EXTRA_CONF_FILE MATCHES "OLED")
set(DTC_OVERLAY_FILE ${CMAKE_CURRENT_SOURCE_DIR}/boards/nucleo_wl55jc_oled.overlay)
endif()
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(EdSaGfmvA)
@ -7,14 +14,21 @@ target_sources(app PRIVATE
src/main.c
src/lora/encryption.c
src/lora/lora.c
#src/lora/synch.c
src/master/master.c
src/epaper/epaper.c
src/utils/constAndVars.c
src/utils/buttons.c
src/utils/displayController.c
src/utils/leds.c
)
if(CONFIG_SLAVE_DISPLAY_TYPE STREQUAL "EPD")
target_sources(app PRIVATE src/epaper/epaper.c)
elseif(CONFIG_SLAVE_DISPLAY_TYPE STREQUAL "OLED")
target_sources(app PRIVATE
src/oled/oled.c
src/oled/font.c
)
endif()
set(DTC_EXTRA_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/dts/bindings")
target_include_directories(app PRIVATE

21
Kconfig
View File

@ -12,3 +12,24 @@ config DEVICE_MODE_SLAVE
bool "Build as slave"
endchoice
choice DEVICE_MODE
prompt "Device Mode"
default DEVICE_MODE_MASTER
config DEVICE_MODE_MASTER
bool "Build as master"
config DEVICE_MODE_SLAVE
bool "Build as slave"
endchoice
config SLAVE_DISPLAY_TYPE
string "Display type (e.g., EPD, OLED)"
depends on DEVICE_MODE_SLAVE
default "UNDEFINED"
config SLAVE_DISPLAY_SLOT
int "Display Slot"
depends on DEVICE_MODE_SLAVE
default 0

View File

@ -12,20 +12,21 @@ BUSY (lila) CN9:7 GPIO B10
OLED
Ports: Anschluss Port
VCC VDD (braun) CN6:4 5V
GND VSS (grau) CN6:6 GND
DIN D0 (blau) CN5:4 GPIO A7
CLK D1 (gelb) CN5:6 GPIO A5
CS CS (orange) CN9:7 GPIO B10 !! A8
DC A0 (grün) CN9:6 GPIO B8 !! A9
RST RST (weiß) CN9:8 GPIO C1 !! A10
VCC (rot) CN6:4 3,3V
GND (schwarz) CN6:6 GND
DIN (blau) CN5:4 GPIO A7
CLK (gelb) CN5:6 GPIO A5
CS (orange) CN5:3 GPIO A4
DC (grün) CN9:6 GPIO B8
RST (weiß) CN9:8 GPIO C1
Bei start:
source zephyrproject/.venv/bin/activate
cd zephyrproject/EdSaGfmvA/
west build -p always -b nucleo_wl55jc .
west build -b <board> -- -DEXTRA_CONF_FILE=conf_EPD.conf
west flash
minicom:

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2024 Marvin Herold
*
* SPDX-License-Identifier: Apache-2.0
*/
&spi1{
status = "okay";
pinctrl-0 = < &spi1_nss_pa4 &spi1_sck_pa5 &spi1_miso_pa6 &spi1_mosi_pa7 >;
pinctrl-names = "default";
epd: epd@0 {
compatible = "solomon,ssd1680";
reg = <0>;
spi-max-frequency = <2000000>;
mipi-max-frequency = <2000000>;
width = <250>;
height = <122>;
rotation = <0>;
dc-gpios = <&gpiob 8 GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpioc 1 GPIO_ACTIVE_HIGH>;
busy-gpios = <&gpiob 10 GPIO_ACTIVE_HIGH>;
cs-gpios = <&gpioa 4 GPIO_ACTIVE_HIGH>;
};
};

View File

@ -6,7 +6,7 @@
* Finale, funktionierende Konfiguration: Wir weichen dem LED-Konflikt
* auf Port B aus, indem wir den sauberen SPI1-Port auf Port A verwenden.
*/
/*
/ {
aliases {
oled = &oled;
@ -32,28 +32,7 @@
// Die anderen GPIOs bleiben unverändert, sie sind nicht im Konflikt.
dc-gpios = <&gpiob 8 GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpioc 1 GPIO_ACTIVE_LOW>;
cs-gpios = <&gpiob 10 GPIO_ACTIVE_LOW>;
cs-gpios = <&gpioa 4 GPIO_ACTIVE_LOW>;
label = "OLED";
};
};*/
&spi1{
status = "okay";
pinctrl-0 = < &spi1_nss_pa4 &spi1_sck_pa5 &spi1_miso_pa6 &spi1_mosi_pa7 >;
pinctrl-names = "default";
epd: epd@0 {
compatible = "solomon,ssd1680";
reg = <0>;
spi-max-frequency = <2000000>;
mipi-max-frequency = <2000000>;
width = <250>;
height = <122>;
rotation = <0>;
dc-gpios = <&gpiob 8 GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpioc 1 GPIO_ACTIVE_HIGH>;
busy-gpios = <&gpiob 10 GPIO_ACTIVE_HIGH>;
cs-gpios = <&gpioa 4 GPIO_ACTIVE_HIGH>;
};
};

4
conf_EPD.conf Normal file
View File

@ -0,0 +1,4 @@
# Konfig für das E-Paper
CONFIG_DEVICE_MODE_SLAVE=y
CONFIG_SLAVE_DISPLAY_TYPE="EPD"
CONFIG_SLAVE_DISPLAY_SLOT=0

4
conf_OLED.conf Normal file
View File

@ -0,0 +1,4 @@
# Konfig für das OLED-Display
CONFIG_DEVICE_MODE_SLAVE=y
CONFIG_SLAVE_DISPLAY_TYPE="OLED"
CONFIG_SLAVE_DISPLAY_SLOT=0

View File

@ -18,6 +18,6 @@ void epd_clear_black(void);
void epd_clear_white(void);
void epd_display_buffer(const unsigned char *buffer);
void draw_something(char toDraw);
void epd_draw_something(char toDraw);
#endif

View File

@ -3,7 +3,6 @@
#include <zephyr/kernel.h>
#include "utils/leds.h"
#include "utils/constAndVars.h"
#define MAX_SAMPLES 10

89
include/oled/lv_font.h Normal file
View File

@ -0,0 +1,89 @@
// File: lv_font.h (muss unter include/oled/lv_font.h liegen)
#ifndef LV_FONT_H
#define LV_FONT_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
// Makro-Definitionen, die in der generierten font.c verwendet werden
#define LV_VERSION_CHECK(major, minor, patch) 0
#ifndef LV_ATTRIBUTE_LARGE_CONST
#define LV_ATTRIBUTE_LARGE_CONST
#endif
// Enum für den Font-Subpixel-Typ
enum { LV_FONT_SUBPX_NONE };
// Enum für den CMap-Typ
typedef uint8_t lv_font_fmt_txt_cmap_type_t;
enum { LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY };
/* Vordeklaration der Haupt-Struktur */
struct _lv_font_t;
/* Struktur zur Beschreibung eines einzelnen Zeichens (Glyph) */
typedef struct {
uint32_t bitmap_index;
uint32_t adv_w;
uint16_t box_w;
uint16_t box_h;
int16_t ofs_x;
int16_t ofs_y;
} lv_font_glyph_dsc_t;
/* Struktur für das Character-Mapping */
typedef struct {
uint32_t range_start;
uint16_t range_length;
uint16_t glyph_id_start;
const void * unicode_list;
const void * glyph_id_ofs_list;
uint16_t list_length;
lv_font_fmt_txt_cmap_type_t type;
} lv_font_fmt_txt_cmap_t;
/* Struktur für Kerning-Paare */
typedef struct {
const void * glyph_ids;
const int8_t * values;
uint16_t pair_cnt;
uint8_t glyph_ids_size;
} lv_font_fmt_txt_kern_pair_t;
/* Haupt-Datenstruktur der Schriftart */
typedef struct {
const uint8_t * glyph_bitmap;
const lv_font_glyph_dsc_t * glyph_dsc;
const lv_font_fmt_txt_cmap_t * cmaps;
const void * kern_dsc;
uint16_t kern_scale;
uint16_t cmap_num;
uint16_t bpp;
uint16_t kern_classes;
uint8_t bitmap_format;
void* cache;
} lv_font_fmt_txt_dsc_t;
/* Die Haupt-Schriftart-Struktur, die Ihr Code verwendet */
typedef struct _lv_font_t {
bool (*get_glyph_dsc)(const struct _lv_font_t *, lv_font_glyph_dsc_t *, uint32_t, uint32_t);
const uint8_t * (*get_glyph_bitmap)(const struct _lv_font_t *, uint32_t);
int16_t line_height;
int16_t base_line;
uint8_t subpx;
int8_t underline_position;
int8_t underline_thickness;
const void * dsc;
const struct _lv_font_t * fallback;
void * user_data;
} lv_font_t;
/* Funktionsprototypen, die in font.c existieren */
bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next);
const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unicode_letter);
/* Makro, um die Schriftart aus Ihrer font.c bekannt zu machen */
#define LV_FONT_DECLARE(font_name) extern const lv_font_t font_name;
#endif /*LV_FONT_H*/

View File

@ -1,17 +1,7 @@
#ifndef OLED_H
#define OLED_H
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/drivers/gpio.h>
#define WIDTH 128
#define HEIGHT 64
#define BYTES_PER_LINE 16 // ((WIDTH + 7) / 8)
#define ALLSCREEN_GRAGHBYTES 1024 //(BYTES_PER_LINE * HEIGHT)
void oled_init(void);
void oled_draw_something(char toDraw);
#endif

View File

@ -1,13 +0,0 @@
#ifndef CONSTANDVARS_H
#define CONSTANDVARS_H
#include <zephyr/kernel.h>
#include <stdint.h>
#include <stdbool.h>
extern bool slave;
extern bool error;
extern bool synchronized;
extern uint32_t nextSynchro;
#endif // CONSTANDVARS_H

View File

@ -0,0 +1,7 @@
#ifndef DISPLAY_CONTROLLER_H
#define DISPLAY_CONTROLLER_H
void dc_init(const char *type_str, int slot);
void dc_draw_something(char to_draw);
#endif

View File

@ -5,7 +5,6 @@
#include <zephyr/drivers/gpio.h>
#include "lora/synch.h"
#include "utils/constAndVars.h"
//#define LED0_NODE DT_ALIAS(led0)

View File

@ -12,5 +12,6 @@ CONFIG_LORA_SHELL=y
CONFIG_DISPLAY=y
CONFIG_SSD16XX=y
# --- Stack Size (unverändert) ---
CONFIG_MAIN_STACK_SIZE=2048

View File

@ -267,7 +267,7 @@ void epd_clear(void) {
void draw_something(char toDraw) {
void epd_draw_something(char toDraw) {
// Muster in den Display-RAM schreiben

View File

@ -251,9 +251,3 @@ const unsigned char HALLO [] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 3920)
const int HALLO_LEN = 3920;
//const unsigned char* HALLO[1] = {
// HALLO
//};

View File

@ -1,3 +1,4 @@
#include <string.h>
#include <zephyr/device.h>
#include <errno.h>
#include <zephyr/sys/util.h>

View File

@ -3,7 +3,7 @@
#include <zephyr/drivers/lora.h>
#include <string.h>
#include "epaper/epaper.h"
#include "utils/displayController.h"
#include "lora/synch.h"
#include "lora/lora.h"
@ -36,8 +36,9 @@ static struct lora_modem_config config = {
static DataPacket packet;
void lora_receive_cb(const struct device *dev, uint8_t *data, uint16_t size,
int16_t rssi, int8_t snr, void *user_data)
void lora_receive_cb(const struct device *dev,
uint8_t *data, uint16_t size,
int16_t rssi, int8_t snr)
{
if (size == sizeof(DataPacket)) {
memcpy(&packet, data, sizeof(DataPacket));
@ -50,7 +51,7 @@ void lora_receive_cb(const struct device *dev, uint8_t *data, uint16_t size,
int enable_lora_receive(void)
{
// Empfang sicher neu starten
lora_recv_async(lora_dev, NULL, NULL);
lora_recv_async(lora_dev, NULL);
memset(&samples, 0, sizeof(samples));
int ret = lora_config(lora_dev, &config);
@ -59,7 +60,7 @@ int enable_lora_receive(void)
return ret;
}
ret = lora_recv_async(lora_dev, lora_receive_cb, NULL);
ret = lora_recv_async(lora_dev, lora_receive_cb);
if (ret != 0) {
printk("❌ Empfang konnte nicht aktiviert werden: %d\n", ret);
return ret;
@ -71,7 +72,7 @@ int enable_lora_receive(void)
int disable_lora_receive(void)
{
int ret = lora_recv_async(lora_dev, NULL, NULL);
int ret = lora_recv_async(lora_dev, NULL);
if (ret != 0) {
printk("❌ Empfang konnte nicht deaktiviert werden: %d\n", ret);
return ret;
@ -93,7 +94,7 @@ void lora_thread(void *p1, void *p2, void *p3)
disable_lora_receive();
if (message_received) {
draw_something('4');
dc_draw_something('4');
}
k_msleep(SLEEP_INTERVAL_MS);
@ -102,7 +103,7 @@ void lora_thread(void *p1, void *p2, void *p3)
void lora_init(void)
{
lora_recv_async(lora_dev, NULL, NULL); // sicher deaktivieren
lora_recv_async(lora_dev, NULL); // sicher deaktivieren
k_thread_create(&lora_thread_data, lora_stack_area, STACK_SIZE,
lora_thread, NULL, NULL, NULL,
PRIORITY, 0, K_NO_WAIT);

View File

@ -26,13 +26,12 @@ uint32_t calculate_offset(uint32_t samples[MAX_SAMPLES])
offsets += samples[i];
}
sync_offset_s = offsets /( MAX_SAMPLES * 3/5);
sync_offset_s = offsets /( MAX_SAMPLES * 3/5)
sync_offset_s -= k_uptime_get();
synchronized = true;
printk("Synchronisiert! Offset: %u Sekunden\n", sync_offset_s);
printk("Synchronisiert! Offset: %u Sekunden\n", sync_offset_s);
return;
}

View File

@ -2,7 +2,7 @@
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include "epaper/epaper.h"
#include "utils/displayController.h"
//#include "oled/oled.h"
#include "lora/lora.h"
@ -11,7 +11,6 @@
#include "utils/buttons.h"
#include "utils/leds.h"
#include "utils/constAndVars.h"
struct k_work_delayable lora_check_work;
@ -42,16 +41,15 @@ void run_master(void) {
// Master-spezifische Logik
}
int run_slave(void)
int run_slave(const char *display_type, int display_slot)
{
printk("Running as SLAVE\n");
if (init_led_and_button() != 0) {
printk("❌ GPIO-Initialisierung fehlgeschlagen\n");
error = true;
return -1;
}
epd_init();
dc_init(display_type, display_slot);
lora_init();
@ -62,12 +60,18 @@ int run_slave(void)
return 0;
}
void main(void) {
int main(void) {
#if IS_ENABLED(CONFIG_DEVICE_MODE_MASTER)
run_master();
return 0;
#elif IS_ENABLED(CONFIG_DEVICE_MODE_SLAVE)
run_slave();
const char *display_type = CONFIG_SLAVE_DISPLAY_TYPE;
int display_slot = CONFIG_SLAVE_DISPLAY_SLOT;
printk("Running slave mode with display type %s (Slot %d)\n", display_type, display_slot);
run_slave(display_type, display_slot);
return 0;
#else
#error "No device mode selected. Please enable one mode in prj.conf or via build flags."
return -1;
#endif
}

View File

@ -29,7 +29,8 @@ struct k_thread input_thread_data;
char latest_word[32] = "Hello!";
struct k_mutex word_mutex;
static DataPacket packet;
//static DataPacket packet;
struct lora_modem_config tx_config_master = {
.frequency = 868100000,
.bandwidth = BW_125_KHZ,

4160
src/oled/font.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,11 +4,32 @@
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>
#include "oled/oled.h"
#include "oled/lv_font.h"
#define OLED_NODE DT_NODELABEL(oled)
#define SPI_BUS DT_BUS(OLED_NODE)
typedef struct {
uint32_t bitmap_index;
uint32_t adv_w;
uint16_t box_w;
uint16_t box_h;
int16_t ofs_x;
int16_t ofs_y;
} my_glyph_dsc_t;
#define OLED_W 128
#define OLED_H 64
#define OLED_PAGES (OLED_H/8)
/* ---- Cursor-Verwaltung --------------------------------------------------- */
static uint8_t cursor_x = 0; /* Pixel */
static uint8_t cursor_y = 0; /* Baseline in Pixel (0..63) */
extern bool my_font_get_glyph_dsc(uint8_t code, my_glyph_dsc_t *out);
extern const uint8_t *my_font_get_bitmap (uint8_t code);
// GPIOs
static const struct gpio_dt_spec oled_cs = GPIO_DT_SPEC_GET(OLED_NODE, cs_gpios);
static const struct gpio_dt_spec oled_dc = GPIO_DT_SPEC_GET(OLED_NODE, dc_gpios);
@ -30,6 +51,11 @@ static struct spi_config spi_cfg = {
#define OLED_RST_ASSERT gpio_pin_set_raw(oled_reset.port, oled_reset.pin, 0)
#define OLED_RST_DEASSERT gpio_pin_set_raw(oled_reset.port, oled_reset.pin, 1)
// ---- prototypes (oberhalb von OLED_Show_Char) ----
static void oled_blit_rowpacked_to_pages(int x0, int y0,
int w, int h,
const uint8_t *bmp);
void oled_driver_delay_xms(uint32_t ms) {
k_msleep(ms);
@ -58,7 +84,7 @@ void OLED_Write_Data(uint8_t *data, size_t len) {
void OLED_Reset(void) {
printk("Führe Hardware-Reset durch (Raw-Modus)...\n");
OLED_RST_ASSERT;
oled_driver_delay_xms(50);
oled_driver_delay_xms(100);
OLED_RST_DEASSERT;
oled_driver_delay_xms(100);
}
@ -68,7 +94,31 @@ void OLED_Reset(void) {
* NEUE, ROBUSTERE INITIALISIERUNGSSEQUENZ (abgeleitet von U8g2 für SSD1309)
* ========================================================================
*/
void OLED_HW_Init(void) {
void oled_init(void) {
printk("OLED Init (Raw-Modus)...\n");
if (!device_is_ready(spi_dev)) {
printk("FATAL: SPI-Gerät nicht bereit!\n"); return;
}
if (!device_is_ready(oled_cs.port)) {
printk("FATAL: CS GPIO Port nicht bereit!\n"); return;
}
if (!device_is_ready(oled_dc.port)) {
printk("FATAL: DC GPIO Port nicht bereit!\n"); return;
}
if (!device_is_ready(oled_reset.port)) {
printk("FATAL: RESET GPIO Port nicht bereit!\n"); return;
}
printk("Konfiguriere Pins für Raw-Output...\n");
gpio_pin_configure_dt(&oled_cs, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&oled_dc, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&oled_reset, GPIO_OUTPUT_INACTIVE);
k_msleep(100);
OLED_Reset();
printk("Sende ROBUSTERE Initialisierungssequenz...\n");
@ -111,11 +161,23 @@ void OLED_HW_Init(void) {
OLED_Write_Command(0xAF); // Display ON
k_msleep(100);
printk("Initialisierung gesendet.\n");
}
void OLED_WhiteScreen_White(void) {
uint8_t buffer[128];
memset(buffer, 0xFF, sizeof(buffer)); // Alles auf 1 setzen für Weiß
for (uint8_t page = 0; page < 8; page++) {
OLED_Write_Command(0xB0 + page); // Set Page Address
OLED_Write_Command(0x00); // Lower column start address
OLED_Write_Command(0x10); // Higher column start address
OLED_Write_Data(buffer, sizeof(buffer));
}
}
void OLED_WhiteScreen_Black(void) {
uint8_t buffer[128];
memset(buffer, 0x00, sizeof(buffer)); // Alles auf 1 setzen für Weiß
for (uint8_t page = 0; page < 8; page++) {
@ -126,35 +188,144 @@ void OLED_WhiteScreen_White(void) {
}
}
void OLED_Testpaints() {
for (uint8_t page = 0; page < 8; page++) {
OLED_Write_Command(0xB0 + page); // Set Page Address
OLED_Write_Command(0x00); // Lower Column Start
OLED_Write_Command(0x10); // Higher Column Start
uint8_t line_data[128];
if (page % 2 == 0) {
memset(line_data, 0xFF, sizeof(line_data)); // Voll (alle Pixel an)
} else {
memset(line_data, 0x00, sizeof(line_data)); // Leer
}
OLED_Write_Data(line_data, sizeof(line_data));
}
}
void OLED_SetCursor(uint8_t x, uint8_t baseline_y) {
cursor_x = x;
cursor_y = baseline_y;
}
/* ---- Hilfsfunktionen ----------------------------------------------------- */
/* liest 1bpp-Pixel (MSB-first) aus einer zeilenweise gepackten Bitmap */
static inline uint8_t read_pixel_1bpp(const uint8_t *bmp,
uint16_t bw, uint16_t bh,
uint16_t x, uint16_t y)
{
if (x >= bw || y >= bh) return 0;
uint16_t bytes_per_row = (bw + 7) / 8;
uint16_t byte_index = y * bytes_per_row + (x >> 3);
uint8_t bit_mask = (uint8_t)(0x80u >> (x & 7)); /* MSB-first */
return (bmp[byte_index] & bit_mask) ? 1u : 0u;
}
/* setzt die Spalten-/Pageadresse im SSD1306 */
static inline void ssd1306_set_pos(uint8_t page, uint8_t col)
{
OLED_Write_Command(0xB0 | (page & 0x07)); /* Page Address */
OLED_Write_Command(0x00 | (col & 0x0F)); /* Low Col Addr */
OLED_Write_Command(0x10 | (col >> 4)); /* High Col Addr */
}
/* ---- Zeichen-Ausgabe ----------------------------------------------------- */
void OLED_Show_Char(char ch)
{
my_glyph_dsc_t gd;
if (!my_font_get_glyph_dsc((uint8_t)ch, &gd)) return;
const uint8_t *bmp = my_font_get_bitmap((uint8_t)ch);
if (!bmp) return;
// x,y nach Wunsch; Bounds prüfen (128x64 anpassen)
int x = 16;
int y = 8;
if (x < 0 || x + gd.box_w > 128 || y < 0 || y + gd.box_h > 64) return;
oled_blit_rowpacked_to_pages(x, y, gd.box_w, gd.box_h, bmp);
// Jetzt korrekt umgepackt blitten
oled_blit_rowpacked_to_pages(x, y, gd.box_w, gd.box_h, bmp);
}
/* Praktisch: String-Ausgabe mit einfacher Zeilenumbruch-Logik */
void OLED_Puts(const char *s)
{
while (*s) {
if (*s == '\n') {
cursor_x = 0;
/* eine Zeile = 8 Pixel Pages; nimm z.B. 16px Zeilenhöhe */
if (cursor_y + 16 < OLED_H) cursor_y += 16;
++s;
continue;
}
OLED_Show_Char(*s++);
}
}
// liest ein Bit aus der zeilenweise (row-packed) LVGL-Bitmap
static inline uint8_t get_bit_rowpacked(const uint8_t *bmp, int x, int y, int w) {
int bit_index = y * w + x; // 1bpp
return (bmp[bit_index >> 3] >> (7 - (bit_index & 7))) & 1;
}
// Quell-Bitmap: row-packed (MSB links), Größe w x h
static void oled_blit_rowpacked_to_pages(int x0, int y0,
int w, int h,
const uint8_t *bmp)
{
if (!bmp || w <= 0 || h <= 0) return;
const int bpr = (w + 7) / 8; // Bytes pro Quellzeile
int page0 = y0 >> 3; // erste Ziel-Page
int y_off = y0 & 7; // vertikaler Bit-Offset innerhalb der Page
int pages = (h + y_off + 7) / 8; // wie viele Pages werden berührt
for (int p = 0; p < pages; p++) {
// Page + Spaltenadresse setzen
OLED_Write_Command(0xB0 + (page0 + p));
OLED_Write_Command(0x00 | (x0 & 0x0F));
OLED_Write_Command(0x10 | ((x0 >> 4) & 0x0F));
// Für jede Spalte ein Byte aufbauen (8 vertikale Pixel)
for (int x = 0; x < w; x++) {
uint8_t out = 0;
for (int bit = 0; bit < 8; bit++) {
int src_y = p * 8 + bit - y_off; // dazugehörige Quellzeile
if ((unsigned)src_y < (unsigned)h) {
// Bit aus row-packed Zeile holen (MSB = linkes Pixel)
int byte_idx = src_y * bpr + (x >> 3);
uint8_t mask = 0x80u >> (x & 7);
if (bmp[byte_idx] & mask) {
out |= (1u << bit);
}
}
}
OLED_Write_Data(&out, 1); // exakt 1 Byte pro Spalte!
}
}
}
void oled_draw_something(char toDraw) {
printk("OLED Init (Raw-Modus)...\n");
OLED_Testpaints();
if (!device_is_ready(spi_dev)) {
printk("FATAL: SPI-Gerät nicht bereit!\n"); return;
}
if (!device_is_ready(oled_cs.port)) {
printk("FATAL: CS GPIO Port nicht bereit!\n"); return;
}
if (!device_is_ready(oled_dc.port)) {
printk("FATAL: DC GPIO Port nicht bereit!\n"); return;
}
if (!device_is_ready(oled_reset.port)) {
printk("FATAL: RESET GPIO Port nicht bereit!\n"); return;
}
k_msleep(2000);
OLED_WhiteScreen_Black();
k_msleep(1000);
printk("Konfiguriere Pins für Raw-Output...\n");
gpio_pin_configure_dt(&oled_cs, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&oled_dc, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&oled_reset, GPIO_OUTPUT_INACTIVE);
k_msleep(100);
OLED_HW_Init();
k_msleep(100); // Kleiner Delay nach der Initialisierung
printk("Display initialisiert. Fülle jetzt den Bildschirm weiß...\n");
OLED_WhiteScreen_White();
OLED_Show_Char('L');
printk("Display-Finish! Der Bildschirm sollte jetzt weiß sein.\n");
}

View File

@ -1,6 +0,0 @@
#include "utils/constAndVars.h"
bool slave = false;
bool error = false;
uint32_t nextSynchro = -1;
bool synchronized = false;

View File

@ -0,0 +1,64 @@
#include <zephyr/kernel.h>
#include <string.h>
#include <stdio.h>
#include "utils/displayController.h"
#include "epaper/epaper.h"
#include "oled/oled.h"
static enum display_type_e {
DISPLAY_NONE,
DISPLAY_OLED,
DISPLAY_EPD
} display_type = DISPLAY_NONE;
static int display_slot = 0;
static bool initialized = false;
void dc_init(const char *type_str, int slot) {
if (initialized) return;
display_slot = slot;
if (strcmp(type_str, "EPD") == 0) {
#if DT_NODE_EXISTS(DT_NODELABEL(epd))
epd_init();
display_type = DISPLAY_EPD;
printk("EPD Display initialisiert (Slot %d)\n", slot);
#else
printk("Fehler: EPD ausgewählt, aber nicht im Devicetree vorhanden!\n");
return;
#endif
} else if (strcmp(type_str, "OLED") == 0) {
#if DT_NODE_EXISTS(DT_NODELABEL(oled))
oled_init();
oled_draw_something('4');
display_type = DISPLAY_OLED;
printk("OLED Display initialisiert (Slot %d)\n", slot);
#endif
} else {
display_type = DISPLAY_NONE;
printk("Unbekannter Displaytyp: %s\n", type_str);
}
initialized = true;
}
void dc_draw_something(char to_draw) {
switch (display_type) {
case DISPLAY_EPD:
#if DT_NODE_EXISTS(DT_NODELABEL(epd))
epd_draw_something(to_draw);
break;
#endif
case DISPLAY_OLED:
#if DT_NODE_EXISTS(DT_NODELABEL(oled))
oled_draw_something(to_draw);
break;
#endif
default:
printk("Kein gültiges Display initialisiert\n");
break;
}
}