/**
 * Infrared přijímač
 * Copyright (c) 2026 Jirka Chráska, <jirka@lixis.cz>
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
// knihovna pro příjem IR dat NEC protokolem
#include "nec_receive.h"

// pro OLED displej SSD1306
#include "ssd1306.h"
#include "font.h"
#define DISPLAY_WIDTH   128			// šířka displeje
#define DISPLAY_HEIGHT  32			// výška displeje
#define I2C_ADDRESS     0x3C		// i2c adresa
#define I2C_FREQ        2000000		// rychlost i2c sběrnice
// rychlost i2c sběrnice může být až 2000000
#define SDA_PIN         4			// datový pin
#define SDC_PIN         5			// hodinový pin
#define I2C             i2c0		// i2c hardware

// struktura pro OLED displej včetně framebufferu
static ssd1306_t disp;
extern bitmapFONT font_spleen_6x12;

// nastavení I2C sběrnice
void setup_i2c(void)
{
    i2c_init(I2C, I2C_FREQ);
    gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(SDC_PIN, GPIO_FUNC_I2C);
    gpio_pull_up(SDA_PIN);
    gpio_pull_up(SDC_PIN);
    // pauza 200ms je nutná kvůli displeji. Pokud není, displej se někdy nerozsvítí
    // pauza 100ms je málo
    sleep_ms(200);
}

// inicializace displeje
void zapnuti_displeje( void )
{
    ssd1306_init(&disp, DISPLAY_WIDTH, DISPLAY_HEIGHT, I2C_ADDRESS, I2C); 
    ssd1306_poweron(&disp); // zapnutí displeje
    ssd1306_clear(&disp);   // vymazání displeje
    ssd1306_contrast(&disp,0x50);
    ssd1306_draw_utf8_string(&disp, 0,  0, &font_spleen_6x12, "Přijímač pro IR NEC");
    ssd1306_draw_utf8_string(&disp, 0, 16, &font_spleen_6x12, "protokol (i extended)");
    ssd1306_show(&disp); // zobrazíme na displeji
}



int main() 
{
char buf[128];
char buf2[128];

    stdio_init_all();

    memset(buf,0,sizeof(buf));
    memset(buf,0,sizeof(buf2));
	// nastavení displeje SSD1306
    setup_i2c();
    zapnuti_displeje();

    PIO pio = pio0;           // výběr PIO (RP2040 má dva: pio0 a pio1)
    uint rx_gpio = 15;        // GPIO pin kde je připojen IR detektor

    // konfigurace a spuštění stavového PIO strojku
    int rx_sm = nec_rx_init(pio, rx_gpio);  // používá 1 SM a 9 instrukcí
    if (rx_sm == -1) {
        printf("Nemohu nakonfigurovat PIO\n");
        return -1;
    }

    // příjem dat
    uint16_t rx_address;
    uint8_t rx_data;
    while (true) {
        memset(buf,0,sizeof(buf));
        memset(buf,0,sizeof(buf2));

        // zobrazení přijatých dat z fronty
        while (!pio_sm_is_rx_fifo_empty(pio, rx_sm)) {
            uint32_t rx_frame = pio_sm_get(pio, rx_sm);
            sprintf(buf2, "Rámec %08x", rx_frame);
            if (nec_decode_frame_ext(rx_frame, &rx_address, &rx_data)) {
                printf("received: F: %08x A: %04x, C: %02x\n", rx_frame, rx_address, rx_data);
                sprintf(buf, "Přijato %04x: %02x '%c'", rx_address, 
                        rx_data, rx_data>=0x20?rx_data:' ');
            } else { 
                printf("received: ERROR %08x\n", rx_frame);
                sprintf(buf, "Chyba protokolu", rx_frame);
            }
            ssd1306_clear(&disp);
            ssd1306_draw_utf8_string(&disp, 0, 0, &font_spleen_6x12, buf);
            ssd1306_draw_utf8_string(&disp, 0,16, &font_spleen_6x12, buf2);
            ssd1306_show(&disp);
        }
        sleep_ms(900);
    }
}
