#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "button.h"
#include "device.h"
#include "cali.h"
#include "user_misc.h"

volatile uint8_t flag_cali_by_button = 0;

static void button_cali_zero(void)
{
    uint8_t ret;
    uint8_t count = 0;

    flag_cali_by_button = 1;
    /* cali zero record */
    for (uint8_t ch = 0; ch < 4; ch++) {
        ret = cali_zero_record(ch);
        if (ret == 0xFF) {
            /* invalid/reference channel */
            continue;
        } else if (ret == 0) {
            /* cali zero record success */
            device_status.cali_zero_record_status[ch] = 0;
        } else {
            /* cali zero record failed */
            device_status.cali_zero_record_status[ch] = ret;
            return;
        }
    }
    /* cali zero active */
    for (uint8_t ch = 0; ch < 4; ch++) {
        ret = cali_zero_activate(ch);
        if (ret == 0xFF) {
            /* invalid/reference channel */
            count++;
            continue;
        } else if (ret == 0) {
            /* cali zero active success */
            device_status.cali_activate_status &= ~(1 << ch);
            count++;
        } else {
            /* cali zero active failed */
            device_status.cali_activate_status |= (1 << ch);
            return;
        }
    }
    flag_cali_by_button = 0;
    /* failed or success */
    if (count >= 4) {
        data_cali_flash.word_remain = CALI_FLASH_WORD_CNT;
        led_ctrl[1].times_volatile = 0;
        led_ctrl[1].times = 3;
        led_ctrl[1].on_volatile = 0;
        led_ctrl[1].on = 5;
        led_ctrl[1].off = 5;
        led_ctrl[1].state_save = led_ctrl[1].state;
        led_ctrl[1].state = LED_BLINK_ON;
    }
}

static void button_cali_restore(void)
{
    flag_cali_by_button = 1;
    for (uint8_t ch = 0; ch < 4; ch++) {
        cali_restore(ch);
        device_status.cali_restore_status &= ~(1 << ch);
    }
    flag_cali_by_button = 0;
    data_cali_flash.word_remain = CALI_FLASH_WORD_CNT;
    led_ctrl[1].times_volatile = 0;
    led_ctrl[1].times = 5;
    led_ctrl[1].on_volatile = 0;
    led_ctrl[1].on = 5;
    led_ctrl[1].off = 5;
    led_ctrl[1].state_save = led_ctrl[1].state;
    led_ctrl[1].state = LED_BLINK_ON;
}

static void button_reset_system(void)
{
    NVIC_SystemReset();
}

void button_init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure = {
        .GPIO_Pin = PIN_BUTTON,
        .GPIO_Mode = GPIO_Mode_IN,
        .GPIO_OType = GPIO_OType_PP,
        .GPIO_Speed = GPIO_Speed_2MHz,
        .GPIO_PuPd = GPIO_PuPd_UP,
    };

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    GPIO_Init(PORT_BUTTON, &GPIO_InitStructure);
}

int button_is_pressed(void)
{
    if (GPIO_ReadInputDataBit(PORT_BUTTON, PIN_BUTTON)) {
        return 0;
    } else {
        return 1;
    }
}

void button_loop(void)
{
    static uint32_t ms = 0;
    static uint32_t cnt_pressed = 0;
    static uint32_t cnt_released = 0;

    if (system_tick_cnt < (ms + 100)) {
        return;
    }
    ms = system_tick_cnt;

    if  (button_is_pressed()) {
        cnt_pressed++;
        cnt_released = 0;
    } else {
        cnt_released++;
        if ((cnt_pressed > 0) && (cnt_released > 2)) {
            if (cnt_pressed < 3) {
                /* do nothing */
            } else if (cnt_pressed < 30) {
                button_cali_zero();
            } else if (cnt_pressed < 75) {
                button_cali_restore();
            } else {
                button_reset_system();
            }
            cnt_released = 0;
            cnt_pressed = 0;
        }
    }
}
