#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"
#include "hardware/clocks.h"
#include "hardware/pwm.h"

#define ADC0_PIN ADC_BASE_PIN
#define ADC1_PIN (ADC_BASE_PIN+1)
#define ADC2_PIN (ADC_BASE_PIN+2)

#define ADC_VREF 3.3f
#define ADC_SAMPLE_CLKS 96

typedef enum {
    adc_input0,
    adc_input1,
    adc_input2,
    adc_input3,
    adc_input4,
} _adc_input_t;

#define PWM_WRAP    4096
#define PWM_OUT_PIN PICO_DEFAULT_LED_PIN
#define PWM_SUB_PIN 2

void adc_irq_handler(void)
{
    while(!adc_fifo_is_empty()) {
        uint16_t value = adc_fifo_get() & 0xFFF;
        pwm_set_gpio_level(PWM_OUT_PIN, value);
        pwm_set_gpio_level(PWM_SUB_PIN, value);
    }
}

int main()
{
    stdio_init_all();

    float adc_div, pwm_clk;
    uint out_slice, sub_slice;

    // PWMの設定
    gpio_set_function(PWM_OUT_PIN, GPIO_FUNC_PWM);
    gpio_set_function(PWM_SUB_PIN, GPIO_FUNC_PWM);

    pwm_config c = pwm_get_default_config();
    pwm_config_set_wrap(&c, PWM_WRAP);
    pwm_config_set_clkdiv(&c, 2.0f);
    // PWMクロックの設定
    pwm_clk = (float)clock_get_hz(clk_sys) / 2.0f / (float)PWM_WRAP;
    printf("pwm_clk = %f\n", pwm_clk);

    out_slice = pwm_gpio_to_slice_num(PWM_OUT_PIN);
    sub_slice = pwm_gpio_to_slice_num(PWM_SUB_PIN);
    pwm_init(out_slice, &c, false);
    pwm_init(sub_slice, &c, false);

    pwm_set_gpio_level(PWM_OUT_PIN, PWM_WRAP);
    pwm_set_gpio_level(PWM_SUB_PIN, PWM_WRAP);

    pwm_set_enabled(out_slice, true);
    pwm_set_enabled(sub_slice, true);
    
    // ADCの設定
    adc_init();
    adc_gpio_init(ADC0_PIN);
    adc_fifo_setup(
        true,       // en: FIFOを有効化するならtrue
        false,      // DREQを有効化するならtrue
        1,          // DREQ、IRQを発生させるFIFOエントリ数
        false,      // 最上位ビットをエラーフラグにするならtrue
        false       // バイトシフトするならtrue
    );
    adc_div = (float)clock_get_hz(clk_adc) / (float)ADC_SAMPLE_CLKS / pwm_clk;
    adc_set_clkdiv(adc_div);
    printf("adc_div = %f\n", adc_div);
    
    // ADC割り込み
	irq_set_exclusive_handler(ADC_IRQ_FIFO, adc_irq_handler);
	irq_set_enabled(ADC_IRQ_FIFO, true);
    // ADC割り込み有効化&フリーランニングスタート
    adc_irq_set_enabled(true);
    adc_run(true);

    while (true) {
        tight_loop_contents();
    }
}
