/*
*********************************************************************************************************
*	函 数 名: main
*	功能说明: c程序入口
*	形    参：无
*	返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/

#include "main.h"
#include "net.h"
#include "os_cpu.h"

int32_t g_recv_msg_flag = 0;

void dump_hex(uint8_t *buffer, uint32_t len)
{

    uint32_t i;
    printf("[DumpHEX]Length:%d ", len);
    for (i = 0; i < len; i++)
    {
        if (i % 16 == 0)
            printf("\r\n");
        else if (i % 8 == 0)
            printf("    ");
        else
            printf(":");
        printf("%02x", buffer[i]);
    }
    printf("\r\n");
}

int main(void)
{
#if 0
    /* 打开GOIOI 端口时钟 */
    *(unsigned int *)(0x40023800 + 0x30) |= (1 << 8);

    /* PI10 为输出 */
    *(unsigned int *)(0x40022000 + 0x00) &= ~((0x03) << (2 * 10));
    *(unsigned int *)(0x40022000 + 0x00) |= (1 << (2 * 10));

    /* PI10 输出高电平 */
    *(unsigned int *)(0x40022000 + 0x14) |= (1 << 10);
    /* PI10 输出低电平 */
    *(unsigned int *)(0x40022000 + 0x14) &= ~(1 << 10);
#elif 0
    bsp_init();
    while (1)
    {
        GPIO_ResetBits(GPIOI, GPIO_Pin_10);
        Delay(0xFFFFFFFF);
        // GPIO_SetBits(GPIOI, GPIO_Pin_10);
        // Delay(0xFFFFFFFF);

        GPIO_ResetBits(GPIOF, GPIO_Pin_7);
        Delay(0xFFFFFF);
        // GPIO_SetBits(GPIOF, GPIO_Pin_7);
        // Delay(0xFFFFFF);

        GPIO_ResetBits(GPIOF, GPIO_Pin_8);
        Delay(0xFFFFFF);
        // GPIO_SetBits(GPIOF, GPIO_Pin_8);
        // Delay(0xFFFFFF);

        GPIO_ResetBits(GPIOC, GPIO_Pin_2);
        Delay(0xFFFFFF);
        // GPIO_SetBits(GPIOC, GPIO_Pin_2);
        // Delay(0xFFFFFF);
    };
#elif 1
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    OSInit();
    bsp_init();
    ftp_server_init();
    iec10x_regist();

    /* init task */
    /* 创建一个启动任务（也就是主任务）。启动任务会创建所有的应用程序任务 */
    OSTaskCreateExt(init_task,                                   /* 启动任务函数指针 */
                    (void *)0,                                   /* 传递给任务的参数 */
                    (OS_STK *)&init_task_stk[INIT_STK_SIZE - 1], /* 指向任务栈栈顶的指针 */
                    INIT_TASK_PRIO,                              /* 任务的优先级，必须唯一，数字越低优先级越高 */
                    INIT_TASK_PRIO,                              /* 任务ID，一般和任务优先级相同 */
                    (OS_STK *)&init_task_stk[0],                 /* 指向任务栈栈底的指针。OS_STK_GROWTH
                                                                    决定堆栈增长方向 */
                    INIT_STK_SIZE,                               /* 任务栈大小 */
                    (void *)0,                                   /* 一块用户内存区的指针，用于任务控制块TCB的扩展功能
                                                                （如任务切换时保存CPU浮点寄存器的数据）。一般不用，填0即可 */
                    OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* 任务选项字 */

    OSStart();

#endif
}

/*!
    \brief      init task
    \param[in]  pvParameters not used
    \param[out] none
    \retval     none
*/
void init_task(void *pvParameters)
{
    uint8_t *p;
    p = pvParameters;
    SysTick_Config(SystemCoreClock / OS_TICKS_PER_SEC);
    /* configure the systick handler priority */
    NVIC_SetPriority(SysTick_IRQn, 0x00U);

    OSTaskCreateExt((void (*)(void *))misc_task,                                              /* 启动任务函数指针 */
                    (void *)0,                                                                /* 传递给任务的参数 */
                    (OS_STK *)&misc_task_stk[MISC_TASK_STK_SIZE - 1],                         /* 指向任务栈栈顶的指针 */
                    (INT8U)MISC_PRIO,                                                         /* 任务的优先级，必须唯一，数字越低优先级越高 */
                    (INT16U)MISC_PRIO,                                                        /* 任务ID，一般和任务优先级相同 */
                    (OS_STK *)&misc_task_stk[0],                                              /* 指向任务栈栈底的指针。OS_STK_GROWTH 决定堆栈增长方向 */
                    (INT32U)MISC_TASK_STK_SIZE,                                               /* 任务栈大小 */
                    (void *)0,                                                                /* 一块用户内存区的指针，用于任务控制块TCB的扩展功能
                                                                                              （如任务切换时保存CPU浮点寄存器的数据）。一般不用，填0即可 */
                    (INT16U)OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP); /* 任务选项字 */

    // OSTaskCreateExt((void (*)(void *))modbus_master_task,
    //                 (void *)0,
    //                 (OS_STK *)&uart1_task_stk[UART1_TASK_STK_SIZE - 1],
    //                 (INT8U)UART1_TASK_PRIO,
    //                 (INT16U)UART1_TASK_PRIO,
    //                 (OS_STK *)&uart1_task_stk[0],
    //                 (INT32U)UART1_TASK_STK_SIZE,
    //                 (void *)0,
    //                 (INT16U)OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP);

    /* 485 modbus从机模式 */
    // OSTaskCreateExt((void (*)(void *))modbus_slave_task,
    //                 (void *)0,
    //                 (OS_STK *)&uart3_task_stk[UART3_TASK_STK_SIZE - 1],
    //                 (INT8U)UART3_TASK_PRIO,
    //                 (INT16U)UART3_TASK_PRIO,
    //                 (OS_STK *)&uart3_task_stk[0],
    //                 (INT32U)UART3_TASK_STK_SIZE,
    //                 (void *)0,
    //                 (INT16U)OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP);

    OSTaskCreateExt((void (*)(void *))iec104_task,
                    (void *)0,
                    (OS_STK *)&iec104_task_stk[IEC_TASK_STK_SIZE - 1],
                    (INT8U)IEC_PRIO,
                    (INT16U)IEC_PRIO,
                    (OS_STK *)&iec104_task_stk[0],
                    (INT32U)IEC_TASK_STK_SIZE,
                    (void *)0,
                    (INT16U)OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP);

    OSTaskCreateExt((void (*)(void *))ftp_server_cmd_task,
                    (void *)0,
                    (OS_STK *)&ftp_server_cmd_task_stk[FTP_CMD_TASK_STK_SIZE - 1],
                    (INT8U)FTP_CMD_PRIO,
                    (INT16U)FTP_CMD_PRIO,
                    (OS_STK *)&ftp_server_cmd_task_stk[0],
                    (INT32U)FTP_CMD_TASK_STK_SIZE,
                    (void *)0,
                    (INT16U)OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP);

    OSTaskCreateExt((void (*)(void *))ftp_server_data_task,
                    (void *)0,
                    (OS_STK *)&ftp_server_data_task_stk[FTP_DATA_TASK_STK_SIZE - 1],
                    (INT8U)FTP_DATA_PRIO,
                    (INT16U)FTP_DATA_PRIO,
                    (OS_STK *)&ftp_server_data_task_stk[0],
                    (INT32U)FTP_DATA_TASK_STK_SIZE,
                    (void *)0,
                    (INT16U)OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP);

    // OSTaskCreateExt((void (*)(void *))modbus_tcp_task,
    //                 (void *)0,
    //                 (OS_STK *)&tcp_task_stk[TCP_TASK_STK_SIZE - 1],
    //                 (INT8U)TCP_PRIO,
    //                 (INT16U)TCP_PRIO,
    //                 (OS_STK *)&tcp_task_stk[0],
    //                 (INT32U)TCP_TASK_STK_SIZE,
    //                 (void *)0,
    //                 (INT16U)OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP);
}

void misc_task(void)
{
    INT8U  cnt      = 0;
    INT16U save_cnt = 0;
    INT8U  temperature;
    INT8U  humidity;
    INT8U  ret;
    // INT8U  key_state;
    AD7606_SetOS(AD_OS_NO);  /* 无过采样 */
    AD7606_SetInputRange(0); /* 0表示输入量程为正负5V, 1表示正负10V */

    // bsp_StartAutoTimer(0, 500); /* 启动1个200ms的自动重装的定时器 */
    AD7606_ReadNowAdc();  /* 读取采样结果 */
    AD7606_StartConvst(); /* 启动1次转换 */
    while (1)
    {
        iwdg_feed(MISC_DOG);
        // key_scan();
        USBH_Process(&USB_OTG_Core, &USB_Host);
        // key_state = key_get();
        // if (key_state != KEY_NONE)
        // {
        //     switch (key_state)
        //     {
        //     case KEY_1_UP:
        //         printf("1111111\r\n");
        //         break;
        //     case KEY_1_DOWN:
        //         printf("wwwwwwwwwwww\r\n");
        //         break;
        //     case KEY_1_LONG:
        //         printf("333333333\r\n");
        //         break;
        //     default:
        //         printf("44444444\r\n");
        //         break;
        //     }
        // }
        if ((cnt % 10 == 0) && (cnt != 0))
        {
            // printf("%ld\r\n", NAND_ReadID());
            // printf("%c\r\n", NOR_ReadByte(0x4000));
        }
        if ((cnt % 25 == 0) && (cnt != 0))
        {
            // printf("%ld\r\n", NAND_ReadID());
            LED2_RUN_TOGGLE;
        }

        if ((cnt % 15 == 0) && (cnt != 0))
        {
            // if (NOR_EraseSector(0x4000) == 0)
            // {
            //     NOR_WriteByte(0x4000, 0xFF);
            // }
        }

        if (cnt == 10)
        {
            // if (am2303_init())
            // {
            //     printf("error\r\n");
            // }
            // else
            // {
            ret = am2303_read_data(&temperature, &humidity); // 读取温湿度值
            // if (ret == 1)
            // {
            //     printf("Temp: (%d).\n", temperature);
            //     printf("Humi: (%d).\n", humidity);
            // }
            // else
            // {
            //     printf("\r\n未发现DHT11温湿度传感器\r\n");
            // }
            // }
        }
        if (cnt >= 25)
        {
            /* 每隔500ms 进来一次. 由软件启动转换 */
            AD7606_ReadNowAdc();  /* 读取采样结果 */
            AD7606_StartConvst(); /* 启动下次转换 */

            cnt = 0; /* 刷新显示 */
        }
        else
        {
            cnt++;
        }

        if (save_cnt >= 25)
        {
            save_cnt = 0;
        }
        else
        {
            save_cnt++;
        }
        if (g_iec104_socket > 0)
        {
            iec104_scheduled(g_iec104_socket);
        }

        iec104_state_machine();
        OSTimeDly(20);
    };
}

// void iec104_task(void)
// {
//     INT8U  buf[MAX_RECV_SIZE] = {0};
//     INT32S ret                = 0;
//     INT32U len                = 0;

//     while (1)
//     {
//         if (g_iec104_socket < 0)
//         {
//             ret = iec104_connect_module();
//             if (ret < 0)
//             {
//                 goto TASK_DELAY;
//             }
//             g_data_req_flag = 0;
//         }
//         else
//         {
//             ret = iec104_rec_master(buf);
//             if (ret <= 0)
//             {
//                 closesocket(g_iec104_socket);
//                 goto TASK_DELAY;
//             }
//         }
// TASK_DELAY:
//         OSTimeDly(100);
//     }
// }

void modbus_tcp_task(void)
{
    INT8U  buf[MAX_RECV_SIZE] = {0};
    INT32S ret                = 0;
    INT16U temp_buf_len;
    INT16U msg_data_len;
    INT32U len;

    while (1)
    {
        if (g_modbus_tcp_socket < 0)
        {
            ret = modbus_tcp_connect_module();
            if (ret < 0)
            {
                goto TASK_DELAY;
            }
            g_data_req_flag = 0;
        }
        else
        {
            ret = modbus_tcp_rec_module(buf);
            if (ret < 2)
            {
                if (g_recv_msg_flag == 1)
                {
                    fly_mosbus_init_flag();
                    closesocket(g_iec104_socket);
                    g_recv_msg_flag = 0;
                }

                goto TASK_DELAY;
            }
            g_recv_msg_flag = 0;
            temp_buf_len    = 0;
            while (temp_buf_len < ret)
            {
                len          = 0;
                msg_data_len = ((buf[temp_buf_len + 1] & 0xff) | ((buf[temp_buf_len + 2] << 8) & 0xff00));
                len          = msg_data_len + 3;
                if (fly_test_process(&(buf[temp_buf_len]), len) != 0)
                {
                    goto TASK_DELAY;
                }
                temp_buf_len += msg_data_len + 3;
            }
        }
TASK_DELAY:
        OSTimeDly(100);
    }
}