#include <stdio.h>
#include <pico/stdlib.h>
#include "hardware/i2c.h"
#include "pico/i2c_slave.h"
#include "hardware/irq.h"
#include "hardware/spi.h"
#include "pico/binary_info.h"
#include "pico/multicore.h"
#include "hardware/irq.h"
#include "hardware/adc.h"
#include "hardware/clocks.h"

#include "ADRS2040U_i2c.h"
#include "adc_driver.hpp"

// ADCドライバ
ADC_Driver adcd;

typedef union {
    uint16_t d;
    uint8_t  b[2];
} WORD_t;


static void i2c_slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event)
{
    static uint8_t ADRS2040U_cmd = ADRS2040_CMD_INVALID;

    switch(event) {
        // I2Cデータ受信
        case I2C_SLAVE_RECEIVE:
            if(ADRS2040U_cmd == ADRS2040_CMD_INVALID) {
                ADRS2040U_cmd = i2c_read_byte_raw(i2c);
            }
            if(ADRS2040U_cmd == ADRS2040_CMD_ADC_START) {
                adcd.run(true);
                ADRS2040U_cmd = ADRS2040_CMD_INVALID;
            }
            else if(ADRS2040U_cmd == ADRS2040_CMD_ADC_STOP) {
                adcd.run(false);
                ADRS2040U_cmd = ADRS2040_CMD_INVALID;

            }
            else if(ADRS2040U_cmd == ADRS2040_CMD_SET_RATE) {
                WORD_t rate;
                i2c_read_raw_blocking(i2c, rate.b, sizeof(WORD_t));
                DEBUG_PRINT("Rate = %d\n", rate.d * 10);
                adcd.set_sample_rate(rate.d * 10);
                ADRS2040U_cmd = ADRS2040_CMD_INVALID;
            }
            break;
        
        // I2Cデータ要求
        case I2C_SLAVE_REQUEST:
            WORD_t sdata;
            sdata.d = 0;

            if(ADRS2040U_cmd == ADRS2040_CMD_GET_COUNT) {
                sdata.d = adcd.count();
            }
            else if(ADRS2040U_cmd == ADRS2040_CMD_GET_VALUE) {
                int value = adcd.get_value();

                if( value >= 0) {
                    sdata.d = value & 0xFFF;
                }
                else {
                    sdata.d = 0xFFFF;
                }
            }
            i2c_write_raw_blocking(i2c, sdata.b, sizeof(WORD_t));
            ADRS2040U_cmd = ADRS2040_CMD_INVALID;

            break;
        // STOP or RESTARTコンデション
        case I2C_SLAVE_FINISH:
            break;
        
        default:
            break;
    }
}

void i2c_setup(void)
{
    i2c_init(i2c0, 100 * 1000);
    gpio_set_function(GPIO_SDA0, GPIO_FUNC_I2C);
    gpio_set_function(GPIO_SCK0, GPIO_FUNC_I2C);
    // ADRS2040Uでは基板上でプルアップされているので
    // プルアップを無効化する
    gpio_disable_pulls(GPIO_SDA0);
    gpio_disable_pulls(GPIO_SCK0);
    // プルアップする場合は以下の通り
//   gpio_pull_up(GPIO_SDA0);
//   gpio_pull_up(GPIO_SCK0);
    // I2Cスレーブ初期化
    i2c_slave_init(i2c0, I2C0_SLAVE_ADDR, &i2c_slave_handler);
}

int main(void)
{
    stdio_init_all();
    i2c_setup();
    while (true)
    {
        ;
    }
}