/* joystick.c
 * Příklad kreslení obdélníka na OLED displeji ssd1306
 * Zpracování hodnot x,y z joysticku
 * (c) Jirka Chráska 2026, <jirka@lixis.cz>
 * BSD 3 clause licence.
 */

#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/adc.h"
#include "ssd1306.h"
#include "font.h"
#include <stdio.h>
#include <string.h>

// pro OLED displej SSD1306
#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
// joystick
#define X_PIN           26
#define Y_PIN           27

// 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);
}

void zapnuti_displeje( void )
{
    ssd1306_init(&disp, DISPLAY_WIDTH, DISPLAY_HEIGHT, I2C_ADDRESS, I2C); // inicializace
    ssd1306_poweron(&disp); // zapnutí displeje
    ssd1306_clear(&disp);   // vymazání displeje
    ssd1306_contrast(&disp,0x50);
    ssd1306_show(&disp); // zobrazíme na displeji
}

int main()
{
char buf[80];

    memset(buf,1,sizeof(buf));
	// nastavení displeje SSD1306
    setup_i2c();
    zapnuti_displeje();
    // nastavení měniče na malý šum
    gpio_set_function(23, GPIO_FUNC_SIO);
    gpio_set_dir( 23, true );
    gpio_put( 23, 1 );
    // inicializace ADC
    adc_gpio_init(X_PIN);
    adc_gpio_init(Y_PIN);
    adc_init();
	// vymazání framebufferu
	ssd1306_clear(&disp);
	// nakreslení obdélníka z horního levého x=0,y=0
	// do dolního levého rohu x=127,y=15
    ssd1306_draw_empty_square(&disp, 0, 0, 127, 15);
	// nakreslení obdélníka z horního levého x=0,y=16
	// do dolního levého rohu x=127,y=31
    ssd1306_draw_empty_square(&disp, 0, 16, 127, 15);
    ssd1306_draw_line(&disp, 63, 1, 63, 30);

    ssd1306_show(&disp); // zobrazíme na displeji

    while(1) {
        adc_select_input(0);
        uint adc_x_raw = adc_read()>>4;
        adc_select_input(1);
        uint adc_y_raw = adc_read()>>4;
        const uint bar_width = 128;
        const uint adc_max = (1<<8) - 1;
        uint bar_x_pos = adc_x_raw * bar_width / adc_max;
        uint bar_y_pos = adc_y_raw * bar_width / adc_max;
        
        ssd1306_clear(&disp);
        ssd1306_draw_empty_square(&disp, 0, 0, 127, 15);
        ssd1306_draw_empty_square(&disp, 0, 16, 127, 15);
        ssd1306_draw_line(&disp, bar_x_pos, 1, bar_x_pos, 15);
        ssd1306_draw_line(&disp, bar_y_pos, 16, bar_y_pos, 31);
        // zpracování x souřadnice joysticku
        sprintf(buf,"x=%d",bar_x_pos);
        if( bar_x_pos == 64 ) {
            ssd1306_draw_utf8_string(&disp, 100,  2, &font_spleen_6x12, buf);
        }
        if( bar_x_pos > 64 ) {
            ssd1306_draw_square(&disp, 64, 0, bar_x_pos - 64, 16);
            ssd1306_draw_utf8_string(&disp, 10,  2, &font_spleen_6x12, buf);
        }
        if( bar_x_pos < 64 ) {
            ssd1306_draw_square(&disp, bar_x_pos, 0, 64 - bar_x_pos, 16);
            ssd1306_draw_utf8_string(&disp, 100,  2, &font_spleen_6x12, buf);
        }
        // zpracování y souřadnice joysticku
        sprintf(buf,"y=%d",bar_y_pos);
        if( bar_y_pos == 64 ) {
            ssd1306_draw_utf8_string(&disp, 100, 18, &font_spleen_6x12, buf);
        }
        if( bar_y_pos > 64 ) {
            ssd1306_draw_square(&disp, 64, 16, bar_y_pos - 64, 16);
            ssd1306_draw_utf8_string(&disp, 10,  18, &font_spleen_6x12, buf);
        }
        if( bar_y_pos < 64 ) {
            ssd1306_draw_square(&disp, bar_y_pos, 16, 64 - bar_y_pos, 16);
            ssd1306_draw_utf8_string(&disp, 100, 18, &font_spleen_6x12, buf);
        }
        ssd1306_show(&disp);
        sleep_ms(5);
    }

    ssd1306_poweroff(&disp);
    // ukončení práce s displejem (uvolnění paměti framebufferu)
    ssd1306_deinit(&disp);
}
