#include "main.h"

unsigned int calccrc(unsigned char crcbuf, unsigned int crc)
{
    unsigned char i;
    unsigned char chk;
    crc = crc ^ crcbuf;
    for (i = 0; i < 8; i++) {
        chk = (unsigned char)(crc & 1);
        crc = crc >> 1;
        crc = crc & 0x7fff;
        if (chk == 1)
            crc = crc ^ 0xa001;
        crc = crc & 0xffff;
    }
    return crc;
}

unsigned int chkcrc(unsigned char *buf, unsigned char len)
{
    unsigned char hi, lo;
    unsigned int i;
    unsigned int crc;
    crc = 0xFFFF;
    for (i = 0; i < len; i++) {
        crc = calccrc(*buf, crc);
        buf++;
    }
    hi = (unsigned char)(crc % 256);
    lo = (unsigned char)(crc / 256);
    crc = (((unsigned int)(hi)) << 8) | lo;
    return crc;
}

void read_data(void)
{
    static int i = 0;
    union crcdata {
        unsigned int word16;
        unsigned char byte[2];
    } crcnow;

    if (read_enable == 1)       // 到时间抄读模块，抄读间隔 1 秒钟(或其他) 
    {
        read_enable = 0;
        Tx_Buffer[0] = Read_ID; //模块的 ID 号，默认 ID 为 0x01 
        Tx_Buffer[1] = 0x03;
        Tx_Buffer[2] = 0x00;
        Tx_Buffer[3] = 0x48;
        Tx_Buffer[4] = 0x00;
        Tx_Buffer[5] = 0x08;
        crcnow.word16 = chkcrc(Tx_Buffer, 6);
        Tx_Buffer[6] = crcnow.byte[1]; //CRC 效验低字节在前
        Tx_Buffer[7] = crcnow.byte[0];

        // 发送数据
        uart_write_blocking(UART0, Tx_Buffer, 8);
        sleep_ms(10);

        // 接收数据
        uint8_t _DATA[37] = { 0 };
        uart_read_blocking(UART0, _DATA, 37);
        for (i = 0; i <= 37 - 1; i++) {
            //printf("0x%X ", _DATA[i]);
            Rx_Buffer[i] = _DATA[i];
        }
        sleep_ms(10);
    }
}

void Analysis_data(void)
{
    unsigned char i;

    union crcdata {
        unsigned int word16;
        unsigned char byte[2];
    } crcnow;

    if (receive_finished == 1)  // 接收完成
    {
        receive_finished = 0;

        if (Rx_Buffer[0] == Read_ID) // 确认 ID 正确
        {
            crcnow.word16 = chkcrc(Rx_Buffer, receive_number - 2); // receive_number 是接收数据总长度
            if ((crcnow.byte[0] == Rx_Buffer[receive_number - 1]) && (crcnow.byte[1] == Rx_Buffer[receive_number - 2])) // 确认 CRC 校验正确
            {
                Voltage_data = (((unsigned long)(Rx_Buffer[3])) << 24) | (((unsigned long)(Rx_Buffer[4])) << 16) | (((unsigned long)(Rx_Buffer[5])) << 8) | Rx_Buffer[6];
                Current_data = (((unsigned long)(Rx_Buffer[7])) << 24) | (((unsigned long)(Rx_Buffer[8])) << 16) | (((unsigned long)(Rx_Buffer[9])) << 8) | Rx_Buffer[10];
                Power_data = (((unsigned long)(Rx_Buffer[11])) << 24) | (((unsigned long)(Rx_Buffer[12])) << 16) | (((unsigned long)(Rx_Buffer[13])) << 8) | Rx_Buffer[14];
                Energy_data = (((unsigned long)(Rx_Buffer[15])) << 24) | (((unsigned long)(Rx_Buffer[16])) << 16) | (((unsigned long)(Rx_Buffer[17])) << 8) | Rx_Buffer[18];
                Pf_data = (((unsigned long)(Rx_Buffer[19])) << 24) | (((unsigned long)(Rx_Buffer[20])) << 16) | (((unsigned long)(Rx_Buffer[21])) << 8) | Rx_Buffer[22];
                CO2_data = (((unsigned long)(Rx_Buffer[23])) << 24) | (((unsigned long)(Rx_Buffer[24])) << 16) | (((unsigned long)(Rx_Buffer[25])) << 8) | Rx_Buffer[26];
                Temperature_data = (((unsigned long)(Rx_Buffer[27])) << 24) | (((unsigned long)(Rx_Buffer[28])) << 16) | (((unsigned long)(Rx_Buffer[29])) << 8) | Rx_Buffer[30];
                Hz_data = (((unsigned long)(Rx_Buffer[31])) << 24) | (((unsigned long)(Rx_Buffer[32])) << 16) | (((unsigned long)(Rx_Buffer[33])) << 8) | Rx_Buffer[34];

            }
        }
    }
}

void Print_data(void)
{
    float voltage_value = (float)Voltage_data * 0.0001;
    printf("电压: %.2f V\n", voltage_value);

    float current_data = (float)Current_data * 0.0001;
    printf("电流: %.2f A\n", current_data);

    float power_data = (float)Power_data * 0.0001;
    printf("功率: %.2f W\n", power_data);

    float energy_data = (float)Energy_data * 0.0001;
    printf("电能: %.2f KWH\n", energy_data);

    float pf_data = (float)Pf_data * 0.001;
    printf("功率因数: %.2f \n", pf_data);

    float cO2_data = (float)CO2_data * 0.0001;
    printf("二氧化碳: %.2f KG\n", cO2_data);

    printf("温度: %.2f ℃\n", (float)Temperature_data * 0.01);
    printf("频率: %.2f HZ\n", (float)Hz_data * 0.01);

    return;
}

// 电能清零
void Electric_energy_(int sec)
{

    uint8_t RETURN_DATA[8] = { 0 };
    uint8_t ELE_ZRRO[13] = { 0x01, 0x10, 0x00, 0x4B, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0xB6, 0x2C };

    // 加入从开机算起60秒后
    if (sec >= 3) {
        printf("电能清零\n");
        uart_write_blocking(UART0, ELE_ZRRO, 13);
        sleep_ms(10);
        uart_read_blocking(UART0, RETURN_DATA, 8);
        for (int i = 0; i <= 8 - 1; i++) {
            printf("0x%X ", RETURN_DATA[i]);
        }
        printf("\n");
    }

    return;
}

static uint16_t IM1253B(void)
{
    static int i = 0;

    // 初始化UART
    uart_init(UART0, BAUD_RATE);
    gpio_set_function(UART0_TX_PIN, GPIO_FUNC_UART);
    gpio_set_function(UART0_RX_PIN, GPIO_FUNC_UART);
    uart_set_hw_flow(UART0, false, false);
    uart_set_format(UART0, DATA_BITS, STOP_BITS, PARITY);
    sleep_ms(10);

    /*
       // 官方软件内部按钮发送的数据
       // 电能清零 TX[13]:01 10 00 4B 00 02 04 00 00 00 00 B6 2C 
       // RX[8]:01 10 00 4B 00 02 31 DE 

       // 读取 TX[8]:00 03 00 01 00 04 14 18 
       // RX[13]:01 03 08 02 35 01 08 41 30 01 05 44 BD  (直流模块)

       // 设置 TX[11]:00 10 00 04 00 01 02 01 05 6B D7 
       // RX[8]:01 10 00 04 00 01 40 08 
     */

    // 发送
    read_enable = 1;
    read_data();
    sleep_ms(10);

    // 发送完成后接收数据并处理
    receive_number = 37;
    receive_finished = 1;
    Analysis_data();

    // 打印原始十六进制数据
    for (i = 0; i <= 37 - 1; i++) {
        printf("0x%X ", Rx_Buffer[i]);
    }
    printf("\n");

    // 打印处理后的数据
    Print_data();

    return 0;
}

int main(void)
{
    stdio_init_all();
    sleep_ms(1000);
    set_sys_clock_khz(250000, true);

    // 启动看门狗, 程序如果有阻塞或者程序逻辑错误重启
    if (watchdog_caused_reboot()) { // 判断是否从看门狗启动或者正常启动
        printf("Rebooted by Watchdog!\n");
    } else {
        printf("Clean boot\n");
    }
    watchdog_enable(8300, 1);   // 8秒检测是否重新加载看门狗计数器. (不更新计数器则重启硬件, 最高8秒(8秒后不喂狗硬件重启))
    watchdog_start_tick(12);

    sec = 0;
    printf("IM1253B Module\n");
    
    while (1) {
        watchdog_update();      // 喂狗

        IM1253B();
        printf("\n");

        // 电能清零
        sec++;
        Electric_energy_(sec);

        sleep_ms(2000);
    }

    return 0;
}
