diff --git a/include/epaper/epaper.h b/include/epaper/epaper.h index bdaa1dc..9558f5e 100644 --- a/include/epaper/epaper.h +++ b/include/epaper/epaper.h @@ -16,7 +16,7 @@ void epd_init(void); void epd_update(void); void epd_clear_black(void); -void epd_clear_white(void); +void epd_clear(); void epd_display_buffer(const unsigned char *buffer); void epd_draw_something(char toDraw); diff --git a/include/lora/encryption.h b/include/lora/encryption.h index 152a147..a88f0dd 100644 --- a/include/lora/encryption.h +++ b/include/lora/encryption.h @@ -6,7 +6,7 @@ extern const uint8_t XOR_KEY; -void xorCrypt(const char *input, char *output, uint8_t key); -uint16_t computeCRC16(const char *data); +size_t xorCryptBytes(const uint8_t *in, uint8_t *out, size_t len, uint8_t key); +uint16_t computeCRC16(const uint8_t *data, size_t len); #endif \ No newline at end of file diff --git a/include/lora/lorapacket.h b/include/lora/lorapacket.h index e849acd..e1d02df 100644 --- a/include/lora/lorapacket.h +++ b/include/lora/lorapacket.h @@ -3,9 +3,13 @@ #include +#define MAX_MSG 64 + typedef struct { - char message[20]; - uint32_t timestamp; + uint16_t len; // Länge der Nutzdaten + uint16_t crc; // CRC über message[0..len-1] + uint32_t timestamp; // z.B. Restzeit / Marker + uint8_t message[MAX_MSG]; } __attribute__((packed)) DataPacket; #endif // LORA_PACKET_H \ No newline at end of file diff --git a/include/lora/synch.h b/include/lora/synch.h index 1718744..e1b73a4 100644 --- a/include/lora/synch.h +++ b/include/lora/synch.h @@ -5,7 +5,6 @@ #define MAX_SAMPLES 10 -// Vorwärtsdeklarationen void synchronite(struct k_work *work); #endif \ No newline at end of file diff --git a/include/oled/font.h b/include/oled/font.h index 26efa1c..f898ac3 100644 --- a/include/oled/font.h +++ b/include/oled/font.h @@ -5,8 +5,7 @@ #include -// Deklarationen der Bitmaps mit 'extern' -// 'extern' sagt dem Compiler: "Diese Variable existiert, aber sie ist in einer anderen .c-Datei definiert." +// Deklarationen der Bitmaps extern const uint8_t oled_fullscreen_A[]; extern const uint8_t oled_fullscreen_B[]; extern const uint8_t oled_fullscreen_C[]; @@ -34,7 +33,6 @@ extern const uint8_t oled_fullscreen_Y[]; extern const uint8_t oled_fullscreen_X[]; extern const uint8_t oled_fullscreen_Z[]; -// Falls du diese auch hast: extern const uint8_t oled_fullscreen_allArray_LEN; extern const uint8_t* oled_fullscreen_allArray[]; diff --git a/include/oled/font_mini.h b/include/oled/font_mini.h index 1343e68..ea427f6 100644 --- a/include/oled/font_mini.h +++ b/include/oled/font_mini.h @@ -3,16 +3,13 @@ #include -// ## 1. Konstanten ## #define CHAR_WIDTH 32 #define CHAR_HEIGHT 16 #define CHAR_BYTES 64 -// ## 2. Globale Variablen (mit "extern") ## extern const uint8_t fullscreen_allArray_LEN; extern const unsigned char* fullscreen_allArray[36]; -// ## 3. Funktions-Prototypen ## typedef void (*set_pixel_func_t)(uint8_t* framebuffer, int fb_width, int x, int y); void set_pixel(uint8_t* framebuffer, int fb_width, int x, int y); void create_fullscreen_char(char character, uint8_t* framebuffer, int fb_width, int fb_height, uint8_t scale); diff --git a/src/epaper/epaper.c b/src/epaper/epaper.c index a69cef8..bb5895c 100644 --- a/src/epaper/epaper.c +++ b/src/epaper/epaper.c @@ -32,13 +32,13 @@ static struct spi_config spi_cfg = { }; // GPIO Makros -#define EPD_W21_CS_0 gpio_pin_set_dt(&epd_cs, 0) -#define EPD_W21_CS_1 gpio_pin_set_dt(&epd_cs, 1) -#define EPD_W21_DC_0 gpio_pin_set_dt(&epd_dc, 0) -#define EPD_W21_DC_1 gpio_pin_set_dt(&epd_dc, 1) -#define EPD_W21_RST_0 gpio_pin_set_dt(&epd_reset, 0) -#define EPD_W21_RST_1 gpio_pin_set_dt(&epd_reset, 1) -#define isEPD_W21_BUSY gpio_pin_get_dt(&epd_busy) +#define EPD_CS_0 gpio_pin_set_dt(&epd_cs, 0) +#define EPD_CS_1 gpio_pin_set_dt(&epd_cs, 1) +#define EPD_DC_0 gpio_pin_set_dt(&epd_dc, 0) +#define EPD_DC_1 gpio_pin_set_dt(&epd_dc, 1) +#define EPD_RST_0 gpio_pin_set_dt(&epd_reset, 0) +#define EPD_RST_1 gpio_pin_set_dt(&epd_reset, 1) +#define isEPD_BUSY gpio_pin_get_dt(&epd_busy) const uint8_t lut_full_update[] = { 0xA0, 0x99, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -56,7 +56,7 @@ void driver_delay_xms(int32_t xms) { void epd_spi_writeByte(uint8_t value) { // Lokaler, nicht optimierbarer Puffer mit expliziter Größe volatile uint8_t tx_data[1]; // Deklariere tx_data lokal, ohne static - tx_data[0] = value; // Initialisiere den Puffer JEDES Mal + tx_data[0] = value; struct spi_buf buf = { .buf = (uint8_t *)tx_data, // explizit casten @@ -75,25 +75,26 @@ void epd_spi_writeByte(uint8_t value) { void epd_readbusy(void) { - while (isEPD_W21_BUSY) { + while (isEPD_BUSY) { k_msleep(100); } } void epd_write_command(uint8_t cmd) { - EPD_W21_DC_0; // DC auf Command setzen + EPD_DC_0; // DC auf Command setzen epd_spi_writeByte(cmd); } void epd_write_data(uint8_t data) { - EPD_W21_DC_1; // DC auf Data setzen + EPD_DC_1; // DC auf Data setzen epd_spi_writeByte(data); } void epd_init_sequence(void) { - EPD_W21_RST_0; + + EPD_RST_0; k_msleep(10); // Ein kurzer Reset-Puls ist oft besser - EPD_W21_RST_1; + EPD_RST_1; k_msleep(100); epd_readbusy(); @@ -138,7 +139,7 @@ void epd_init_sequence(void) { epd_write_command(0x18); // Temperature Sensor Control epd_write_data(0x80); // Internen Sensor verwenden - // Schreibe die finale LUT in den Controller + // Schreibe die LUT in den Controller epd_write_command(0x32); for (int i = 0; i < sizeof(lut_full_update); i++) { epd_write_data(lut_full_update[i]); @@ -174,127 +175,106 @@ void epd_init(void){ epd_clear(); // Zweiter Clear-Durchgang // vor dem Malen den Cursor auf den Anfang (0,0) setzen - EPD_W21_CS_0; + EPD_CS_0; epd_write_command(0x4E); // Setze X-Adress-Zähler auf 0 epd_write_data(0x00); epd_write_command(0x4F); // Setze Y-Adress-Zähler auf 0 epd_write_data(0x00); epd_write_data(0x00); - EPD_W21_CS_1; + EPD_CS_1; } + void epd_update(void) { epd_write_command(0x22); - epd_write_data(0xC7); //war FF + epd_write_data(0xFF); //war FF epd_write_command(0x20); epd_readbusy(); } + void epd_setPosition(void) { + // 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 + } -// 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_setPosition(); + EPD_CS_0; // <-- CS hier aktivieren (LOW) epd_write_command(0x24); // Command: write RAM for black/white image for (int i = 0; i < ALLSCREEN_GRAGHBYTES; i++) { epd_write_data(datas[i]); } - EPD_W21_CS_1; // <-- CS hier deaktivieren (HIGH) + EPD_CS_1; // <-- CS hier deaktivieren (HIGH) // Der Update-Befehl ist eine eigene Transaktion - EPD_W21_CS_0; + EPD_CS_0; epd_update(); - EPD_W21_CS_1; + EPD_CS_1; } // Beispiel für das komplette Löschen des Bildschirms void epd_whitescreen_black(void) { - EPD_W21_CS_0; // <-- CS hier aktivieren (LOW) + epd_setPosition(); + EPD_CS_0; // <-- CS hier aktivieren (LOW) epd_write_command(0x24); for (int i = 0; i < ALLSCREEN_GRAGHBYTES; i++) { epd_write_data(0x00); // Schwarz } - EPD_W21_CS_1; // <-- CS hier deaktivieren (HIGH) + EPD_CS_1; // <-- CS hier deaktivieren (HIGH) // Der Update-Befehl ist eine eigene Transaktion - EPD_W21_CS_0; + EPD_CS_0; epd_update(); - EPD_W21_CS_1; -} -// Dasselbe musst du für EPD_WhiteScreen_White() machen. - - -void epd_whitescreen_white(void) { - EPD_W21_CS_0; // <-- CS hier aktivieren (LOW) - epd_write_command(0x24); - for (int i = 0; i < ALLSCREEN_GRAGHBYTES; i++) { - epd_write_data(0xFF); // Weiß - } - EPD_W21_CS_1; // <-- CS hier deaktivieren (HIGH) - - // Der Update-Befehl ist eine eigene Transaktion - EPD_W21_CS_0; - epd_update(); - EPD_W21_CS_1; + EPD_CS_1; } void epd_clear(void) { + epd_setPosition(); 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; + EPD_CS_0; epd_write_command(0x24); // Schreibe in den RAM for (int i = 0; i < ALLSCREEN_GRAGHBYTES; i++) { epd_write_data(0xFF); // 0xFF = Weiß } - EPD_W21_CS_1; + EPD_CS_1; // Physisches Update starten, um den Bildschirm zu reinigen - EPD_W21_CS_0; + EPD_CS_0; epd_update(); - EPD_W21_CS_1; + EPD_CS_1; epd_readbusy(); // Warten, bis der Clear-Vorgang abgeschlossen ist } void epd_draw_something(char toDraw) { + draw_char(toDraw, epaper_framebuffer, 256, HEIGHT, 17); epd_whitescreen_all(epaper_framebuffer); - draw_char('K', epaper_framebuffer, 256, HEIGHT, 17); - - EPD_W21_CS_0; - epd_write_command(0x24); - for (int i = 0; i < ALLSCREEN_GRAGHBYTES; i++) { - epd_write_data(epaper_framebuffer[i]); - } - EPD_W21_CS_1; - - - // Physisches Update - printk("Aktualisiere Display...\n"); - EPD_W21_CS_0; - epd_update(); - EPD_W21_CS_1; printk("Display-Finish.\n"); -} \ No newline at end of file + + epd_readbusy(); // BUSY = 0 → bereit + + epd_write_command(0x02); // POWER_OFF + epd_readbusy(); // warten bis off + + epd_write_command(0x10); // DEEP_SLEEP + epd_write_data(0x01); + k_msleep(5); + + gpio_pin_set_dt(&epd_cs, 0); + gpio_pin_set_dt(&epd_dc, 0); + gpio_pin_set_dt(&epd_reset, 0); +} diff --git a/src/epaper/font_mini.c b/src/epaper/font_mini.c index 5c2a4e8..3698203 100644 --- a/src/epaper/font_mini.c +++ b/src/epaper/font_mini.c @@ -6,65 +6,65 @@ // 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 + 0x00, 0x00, 0x00, 0x00, 0x00, // sp + 0x00, 0x00, 0x5F, 0x00, 0x00, // ! + 0x00, 0x07, 0x00, 0x07, 0x00, // " + 0x14, 0x7F, 0x14, 0x7F, 0x14, // # + 0x12, 0x2A, 0x7F, 0x2A, 0x24, // $ + 0x62, 0x64, 0x08, 0x13, 0x23, // % + 0x50, 0x22, 0x55, 0x49, 0x36, // & + 0x00, 0x00, 0x03, 0x05, 0x00, // ' + 0x00, 0x41, 0x22, 0x1C, 0x00, // ( + 0x00, 0x1C, 0x22, 0x41, 0x00, // ) + 0x08, 0x2A, 0x1C, 0x2A, 0x08, // * + 0x08, 0x08, 0x3E, 0x08, 0x08, // + + 0x00, 0x00, 0x30, 0x50, 0x00, // , + 0x08, 0x08, 0x08, 0x08, 0x08, // - + 0x00, 0x00, 0x60, 0x60, 0x00, // . + 0x02, 0x04, 0x08, 0x10, 0x20, // / + 0x3E, 0x45, 0x49, 0x51, 0x3E, // 0 + 0x00, 0x40, 0x7F, 0x42, 0x00, // 1 + 0x46, 0x49, 0x51, 0x61, 0x42, // 2 + 0x31, 0x4B, 0x45, 0x41, 0x21, // 3 + 0x10, 0x7F, 0x12, 0x14, 0x18, // 4 + 0x39, 0x45, 0x45, 0x45, 0x27, // 5 + 0x3C, 0x66, 0x66, 0x49, 0x3C, // 6 + 0x03, 0x05, 0x09, 0x71, 0x01, // 7 + 0x36, 0x49, 0x49, 0x49, 0x36, // 8 + 0x1E, 0x29, 0x49, 0x49, 0x06, // 9 + 0x00, 0x00, 0x36, 0x36, 0x00, // : + 0x00, 0x00, 0x36, 0x56, 0x00, // ; + 0x41, 0x22, 0x14, 0x08, 0x00, // < + 0x14, 0x14, 0x14, 0x14, 0x14, // = + 0x00, 0x08, 0x14, 0x22, 0x41, // > + 0x06, 0x09, 0x51, 0x01, 0x02, // ? + 0x3E, 0x41, 0x79, 0x49, 0x32, // @ + 0x7E, 0x11, 0x11, 0x11, 0x7E, // A + 0x36, 0x49, 0x49, 0x49, 0x7F, // B + 0x22, 0x41, 0x41, 0x41, 0x3E, // C + 0x1C, 0x22, 0x41, 0x41, 0x7F, // D + 0x41, 0x49, 0x49, 0x49, 0x7F, // E + 0x01, 0x01, 0x09, 0x09, 0x7F, // F + 0x32, 0x51, 0x41, 0x41, 0x3E, // G + 0x7F, 0x08, 0x08, 0x08, 0x7F, // H + 0x00, 0x41, 0x7F, 0x41, 0x00, // I + 0x01, 0x3F, 0x41, 0x40, 0x20, // J + 0x41, 0x22, 0x14, 0x08, 0x7F, // K + 0x40, 0x40, 0x40, 0x40, 0x7F, // L + 0x7F, 0x02, 0x04, 0x02, 0x7F, // M + 0x7F, 0x10, 0x08, 0x04, 0x7F, // N + 0x3E, 0x41, 0x41, 0x41, 0x3E, // O + 0x06, 0x09, 0x09, 0x09, 0x7F, // P + 0x5E, 0x21, 0x51, 0x41, 0x3E, // Q + 0x46, 0x29, 0x19, 0x09, 0x7F, // R + 0x31, 0x49, 0x49, 0x49, 0x46, // 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 + 0x43, 0x45, 0x49, 0x51, 0x61, // Z }; void draw_char(char character, uint8_t* framebuffer, int fb_width, int fb_height, uint8_t scale) { @@ -77,10 +77,8 @@ void draw_char(char character, uint8_t* framebuffer, int fb_width, int fb_height } const uint8_t* font_ptr = font5x7 + (character - ' ') * 5; - int scaled_width = 5 * scale; - int scaled_height = 7 * scale; - int start_x = 0;//(fb_width - scaled_width) / 2; - int start_y = 0;//(fb_height - scaled_height) / 2; + int start_x = 0; + int start_y = 0; // Zeichen Pixel für Pixel malen for (int y = 0; y < 7; y++) { // Höhe des Fonts ist 7 diff --git a/src/lora/encryption.c b/src/lora/encryption.c index 553af3c..81ac797 100644 --- a/src/lora/encryption.c +++ b/src/lora/encryption.c @@ -7,25 +7,19 @@ #include "lora/encryption.h" -const uint8_t XOR_KEY = 0x5Au; - void xorCrypt(const char *input, char *output, uint8_t key) { - size_t len = strlen(input); - for (size_t i = 0; i < len; i++) { - output[i] = input[i] ^ key; - } - output[len] = '\0'; // Null-Terminierung für gültige C-Strings +size_t xorCryptBytes(const uint8_t *in, uint8_t *out, size_t len, uint8_t key) { + for (size_t i = 0; i < len; i++) out[i] = in[i] ^ key; + return len; } -uint16_t computeCRC16(const char *data) { + +uint16_t computeCRC16(const uint8_t *data, size_t len) { uint16_t crc = 0xFFFF; - for (size_t i = 0; i < strlen(data); i++) { - crc ^= (uint8_t)data[i] << 8; + for (size_t i = 0; i < len; i++) { + crc ^= (uint16_t)data[i] << 8; for (int j = 0; j < 8; j++) { - if (crc & 0x8000) - crc = (crc << 1) ^ 0x1021; - else - crc <<= 1; + crc = (crc & 0x8000) ? (uint16_t)((crc << 1) ^ 0x1021) : (uint16_t)(crc << 1); } } return crc; diff --git a/src/lora/lora.c b/src/lora/lora.c index b8d20ca..a590403 100644 --- a/src/lora/lora.c +++ b/src/lora/lora.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "utils/displayController.h" @@ -17,7 +18,7 @@ const struct device *lora_dev = DEVICE_DT_GET(DT_ALIAS(lora0)); static volatile int rx_count = 0; static volatile bool message_received = false; -char decoded[128]; +static char decoded[MAX_MSG + 1]; uint32_t sleep_intervall_ms = 1; uint32_t start = 0; @@ -36,26 +37,41 @@ static struct lora_modem_config config = { .tx = false, }; -static DataPacket packet; 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)); - rx_count++; - sleep_intervall_ms = (120000 + packet.timestamp); - printk("timestamp: %d, next: %d\n", packet.timestamp, sleep_intervall_ms); - printk("Nachricht empfangen (%d Bytes): %s\n", rx_count, packet.message); - uint32_t stop = k_uptime_get() - start; - - xorCrypt(data, decoded, 0x5A); - message_received = true; - - printk("Zeitpunkt: %d\n", stop); - disable_lora_receive(); +{ + // Minimaler Header: 2(len)+2(crc)+4(ts) = 8 + if (size < 8) return; + + // Felder aus Big-Endian lesen + uint16_t len = sys_get_be16(&data[0]); + uint16_t rx_crc = sys_get_be16(&data[2]); + uint32_t ts_ms = sys_get_be32(&data[4]); + + if (len > MAX_MSG) return; + if (size < 8 + len) return; // unvollständig + + const uint8_t *msg = &data[8]; + + // CRC prüfen (über verschlüsselte Payload) + uint16_t calc = computeCRC16(msg, len); + if (calc != rx_crc) { + printk("CRC-Fehler: %04x != %04x\n", rx_crc, calc); + return; } + + // Entschlüsseln (erst NACH erfolgreicher CRC) + size_t out_len = xorCryptBytes(msg, (uint8_t*)decoded, len, 0x5A); + decoded[out_len] = '\0'; + + sleep_intervall_ms = (120000 + ts_ms); + + message_received = true; + disable_lora_receive(); + + } int enable_lora_receive(void) @@ -103,11 +119,18 @@ void lora_thread(void *p1, void *p2, void *p3) disable_lora_receive(); + int64_t t0 = k_uptime_get(); + if (message_received) { dc_draw_something(decoded); } + + int64_t timeToDraw = k_uptime_get() - t0; + int64_t to_sleep = (int64_t)sleep_intervall_ms - timeToDraw; - k_msleep(sleep_intervall_ms); + if (to_sleep > 0) { + k_msleep((int32_t)to_sleep); + } } } diff --git a/src/master/master.c b/src/master/master.c index 4e74ba8..4dd67b9 100644 --- a/src/master/master.c +++ b/src/master/master.c @@ -1,9 +1,10 @@ -#include -#include #include -#include #include +#include +#include #include +#include // sys_cpu_to_be16/32, sys_be16_to_cpu +#include #include #include @@ -11,129 +12,145 @@ #include "lora/lorapacket.h" #define DEFAULT_RADIO_NODE DT_ALIAS(lora0) -#define SEND_INTERVAL_MS 1000 // Sendeintervall in ms +#define UART_DEVICE_NODE DT_CHOSEN(zephyr_console) +#define STACK_SIZE 1024 +#define INPUT_STACK_SIZE 1024 +#define INPUT_PRIORITY 5 + +#define ACTIVE_TIME_MS 10000 +#define SEND_INTERVAL_MS 1000 #define SLEEP_INTERVAL_MS 120000 -#define STACK_SIZE 1024 -#define INPUT_STACK_SIZE 1024 -#define INPUT_PRIORITY 5 - -struct k_thread send_thread_data; +#define MAX_MSG 64 const struct device *lora_dev_master = DEVICE_DT_GET(DEFAULT_RADIO_NODE); +const struct device *uart_console = DEVICE_DT_GET(UART_DEVICE_NODE); -K_THREAD_STACK_DEFINE(send_stack_area, STACK_SIZE); +K_THREAD_STACK_DEFINE(send_stack_area, STACK_SIZE); K_THREAD_STACK_DEFINE(input_stack_area, INPUT_STACK_SIZE); -struct k_thread input_thread_data; +static struct k_thread send_thread_data; +static struct k_thread input_thread_data; +static struct k_mutex word_mutex; -char latest_word[32] = "Hello!"; -char encrypted[64]; -struct k_mutex word_mutex; +static char latest_word[32] = "HALLO!"; -struct lora_modem_config tx_config_master = { - .frequency = 868100000, - .bandwidth = BW_125_KHZ, - .datarate = SF_7, +static struct lora_modem_config tx_config_master = { + .frequency = 868100000, + .bandwidth = BW_125_KHZ, + .datarate = SF_7, .preamble_len = 8, - .coding_rate = CR_4_5, - .tx_power = 14, - .tx = true, + .coding_rate = CR_4_5, + .tx_power = 14, + .tx = true, }; -#define UART_DEVICE_NODE DT_CHOSEN(zephyr_console) -const struct device *uart_console = DEVICE_DT_GET(UART_DEVICE_NODE); - -void uart_input_get_line(char *buf, size_t max_len) +static void uart_input_get_line(char *buf, size_t max_len) { size_t len = 0; char c; - while (len < max_len - 1) { if (uart_poll_in(uart_console, &c) == 0) { - if (c == '\r' || c == '\n') { - break; - } + if (c == '\r' || c == '\n') break; buf[len++] = c; - printk("%c", c); // Echo + printk("%c", c); // Echo } k_msleep(1); } - buf[len] = '\0'; printk("\n"); } - -void send_lora_message(const char* text, uint32_t timer) +static int build_packet_snapshot(DataPacket *out_pkt, uint32_t timer_ms, char *dbg_plain, size_t dbg_sz) { - int ret = lora_config(lora_dev_master, &tx_config_master); - if (ret != 0) { - printk("LoRa-Konfiguration fehlgeschlagen: %d\n", ret); - return; + char local_plain[sizeof(latest_word)]; + k_mutex_lock(&word_mutex, K_FOREVER); + strncpy(local_plain, latest_word, sizeof(local_plain)); + local_plain[sizeof(local_plain)-1] = '\0'; + k_mutex_unlock(&word_mutex); + + for (size_t i = 0; local_plain[i] != '\0'; ++i) { + local_plain[i] = (char)toupper((unsigned char)local_plain[i]); } - DataPacket pkt; + uint8_t local_enc[MAX_MSG]; + size_t plain_len = strnlen(local_plain, sizeof(local_plain)); + if (plain_len > MAX_MSG) plain_len = MAX_MSG; - memset(&pkt, 0, sizeof(pkt)); - strncpy(pkt.message, encrypted, sizeof(pkt.message)); - pkt.timestamp = timer; + size_t local_len = xorCryptBytes((const uint8_t*)local_plain, local_enc, plain_len, 0x5A); + uint16_t local_crc = computeCRC16(local_enc, local_len); - ret = lora_send(lora_dev_master, (uint8_t *)&pkt, sizeof(pkt)); - if (ret < 0) { - printk("Senden fehlgeschlagen: %d\n", ret); - } else { - printk("Gesendet: \"%s\"\n", encrypted); + memset(out_pkt, 0, sizeof(*out_pkt)); + out_pkt->len = sys_cpu_to_be16((uint16_t)local_len); + out_pkt->crc = sys_cpu_to_be16(local_crc); + out_pkt->timestamp = sys_cpu_to_be32(timer_ms); + memcpy(out_pkt->message, local_enc, local_len); + + if (dbg_plain && dbg_sz) { + strncpy(dbg_plain, local_plain, dbg_sz); + dbg_plain[dbg_sz - 1] = '\0'; } + return (int)local_len; } -void send_loop_thread(void *p1, void *p2, void *p3) +static int send_packet_snapshot(const DataPacket *pkt, size_t payload_len) { - const int active_time_ms = 10000; - const int interval_ms = 1000; + size_t total = sizeof(pkt->len) + sizeof(pkt->crc) + sizeof(pkt->timestamp) + payload_len; + return lora_send(lora_dev_master, (uint8_t *)pkt, total); +} - char local_copy[32]; +static void send_loop_thread(void *p1, void *p2, void *p3) +{ + DataPacket snapshot; + size_t snap_len = 0; while (1) { - printk("Sendephase gestartet\n"); - // Wort einfrieren - k_mutex_lock(&word_mutex, K_FOREVER); - strncpy(local_copy, encrypted, sizeof(local_copy)); - local_copy[sizeof(local_copy) - 1] = '\0'; - k_mutex_unlock(&word_mutex); - uint32_t start = k_uptime_get(); - while ((k_uptime_get() - start) < active_time_ms) { - send_lora_message(local_copy, (active_time_ms - (k_uptime_get() - start))); - k_msleep(interval_ms); + + // Vor dem aktiven Fenster: Snapshot bauen + char dbg[33]; + snap_len = (size_t)build_packet_snapshot(&snapshot, /*timer*/ACTIVE_TIME_MS, dbg, sizeof(dbg)); + printk("Snapshot von \"%s\" (len=%u)\n", dbg, (unsigned)snap_len); + + while ((k_uptime_get() - start) < ACTIVE_TIME_MS) { + uint32_t remaining = ACTIVE_TIME_MS - (k_uptime_get() - start); + + ((DataPacket*)&snapshot)->timestamp = sys_cpu_to_be32(remaining); + + int ret = send_packet_snapshot(&snapshot, snap_len); + if (ret < 0) { + printk("Senden fehlgeschlagen: %d\n", ret); + } + k_msleep(SEND_INTERVAL_MS); } printk("Sendephase beendet\n"); - printk("Warte 120 Sekunden...\n"); + printk("Schlafe %u ms…\n", (unsigned)SLEEP_INTERVAL_MS); k_msleep(SLEEP_INTERVAL_MS); } } -void input_thread(void *p1, void *p2, void *p3) +static void input_thread(void *p1, void *p2, void *p3) { - char buffer[32]; + char buffer[sizeof(latest_word)]; while (1) { printk("Neues Wort eingeben:\n"); uart_input_get_line(buffer, sizeof(buffer)); + for (size_t i = 0; buffer[i] != '\0'; ++i) { + buffer[i] = (char)toupper((unsigned char)buffer[i]); + } + k_mutex_lock(&word_mutex, K_FOREVER); strncpy(latest_word, buffer, sizeof(latest_word)); latest_word[sizeof(latest_word) - 1] = '\0'; k_mutex_unlock(&word_mutex); printk("Neues Wort gespeichert: \"%s\"\n", latest_word); - xorCrypt(latest_word, encrypted, 0x5A); } - - } void master_init(void) @@ -142,11 +159,24 @@ void master_init(void) printk("LoRa-Gerät nicht bereit\n"); return; } - + if (!device_is_ready(uart_console)) { + printk("UART-Konsole nicht bereit\n"); + return; + } + + int ret = lora_config(lora_dev_master, &tx_config_master); + if (ret) { + printk("LoRa-Konfiguration fehlgeschlagen: %d\n", ret); + return; + } + k_mutex_init(&word_mutex); - xorCrypt(latest_word, encrypted, 0x5A); + k_thread_create(&input_thread_data, input_stack_area, INPUT_STACK_SIZE, - input_thread, NULL, NULL, NULL, INPUT_PRIORITY, 0, K_NO_WAIT); - k_thread_create(&send_thread_data, send_stack_area, STACK_SIZE, - send_loop_thread, NULL, NULL, NULL, INPUT_PRIORITY, 0, K_NO_WAIT); + input_thread, NULL, NULL, NULL, + INPUT_PRIORITY, 0, K_NO_WAIT); + + k_thread_create(&send_thread_data, send_stack_area, STACK_SIZE, + send_loop_thread, NULL, NULL, NULL, + INPUT_PRIORITY, 0, K_NO_WAIT); } diff --git a/src/oled/oled.c b/src/oled/oled.c index f0fa6df..de28eb0 100644 --- a/src/oled/oled.c +++ b/src/oled/oled.c @@ -108,12 +108,12 @@ void oled_init(void) { oled_write_cmd(0xDA); // Set COM Pins oled_write_cmd(0x12); oled_write_cmd(0x81); // Set Contrast - oled_write_cmd(0xCF); + oled_write_cmd(0x80); oled_write_cmd(0xD9); // Set Pre-charge Period - oled_write_cmd(0xF1); + oled_write_cmd(0x22); oled_write_cmd(0xDB); // Set VCOMH oled_write_cmd(0x40); - oled_write_cmd(0xA4); // Entire Display ON + oled_write_cmd(0x34); // Entire Display ON oled_write_cmd(0xA6); // Normal Display oled_write_cmd(0x8D); // Charge Pump oled_write_cmd(0x14); // Enable diff --git a/src/utils/displayController.c b/src/utils/displayController.c index f9c494d..7c1a328 100644 --- a/src/utils/displayController.c +++ b/src/utils/displayController.c @@ -22,7 +22,7 @@ void dc_init(const char *type_str, int slot) { if (strcmp(type_str, "EPD") == 0) { #if DT_NODE_EXISTS(DT_NODELABEL(epd)) epd_init(); - epd_draw_something(' '); + epd_draw_something(' '); display_type = DISPLAY_EPD; printk("EPD Display initialisiert (Slot %d)\n", slot); #else @@ -34,7 +34,7 @@ void dc_init(const char *type_str, int slot) { } else if (strcmp(type_str, "OLED") == 0) { #if DT_NODE_EXISTS(DT_NODELABEL(oled)) oled_init(); - oled_draw_something(' '); + oled_draw_something(' '); display_type = DISPLAY_OLED; printk("OLED Display initialisiert (Slot %d)\n", slot); #endif @@ -51,6 +51,7 @@ void dc_draw_something(const char *message) { switch (display_type) { case DISPLAY_EPD: #if DT_NODE_EXISTS(DT_NODELABEL(epd)) + epd_init(); epd_draw_something(to_draw); break; #endif