#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pio.h"

#include "dht11.pio.h"

#define DHT11_SDA   16
#define DHT11_START_PULSE_US (20 * 1000) 

volatile static uint temperature = 0;
volatile static uint humidity = 0;

void pio_irq_handler(void)
{
    static int p = 0;
    static uint8_t buffer[5];
    // 1バイトの取り込みを行う
    if(pio_interrupt_get(pio0, 0)) {
        // 割り込みフラグ0クリア
        pio_interrupt_clear(pio0, 0);
        // データをpull
        buffer[p++] = pio_sm_get(pio0, 0) & 0xFF;
    }
    // 5バイト（40ビットの取り込み完了
    if(pio_interrupt_get(pio0,1)){
        // 割り込みフラグ1クリア
        pio_interrupt_clear(pio0, 1);
        p = 0;  // ポインタ初期化
        uint8_t checksum = (buffer[0]+buffer[1]+buffer[2]+buffer[3]) & 0xFF;
        if( checksum == buffer[4]){
            // データ正常
            // DHT-11では小数部は切り捨ててしまう
            temperature = buffer[2];
            humidity = buffer[0];
        }
    }
}

// repeating_timerオブジェクト
struct repeating_timer rtimer;

bool update_dht11_data(__unused struct repeating_timer *t)
{
    pio_sm_put(pio0, 0, DHT11_START_PULSE_US);
    return true;        // falseを返すとリピート動作が終了
}

int main()
{
    stdio_init_all();
    // CPUのPIO0_IRQ0に割り込みハンドラpio_irq_handlerを割り当てる
    irq_set_exclusive_handler(PIO0_IRQ_0, pio_irq_handler);
    // PIO0_IRQ0を有効化
    irq_set_enabled(PIO0_IRQ_0, true);
    // PIO0_IRQ0に割り込みフラグ0、1を割り当てる
    pio_set_irq0_source_enabled(pio0, pis_interrupt0, true);
    pio_set_irq0_source_enabled(pio0, pis_interrupt1, true);
    // 
    uint offset = pio_add_program(pio0, &dht11_program);
    dht11_program_init(pio0, 0, offset, DHT11_SDA);
    pio_sm_set_enabled(pio0, 0, true);

    // 繰り返し実行する関数を登録する
    add_repeating_timer_ms(2*1000, update_dht11_data, NULL, &rtimer);
    while(true) {
        sleep_ms(2000);
        printf("hum = %d %%, temp = %d C\n", humidity, temperature);
    }
}
