/**
 * \file    sys_uart1.c
 * \brief   UART1 handler
 * 
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-08-01
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-08-01  Original Creation
 * 
 */

#include "libc.h"
#include "drivers.h"
#include "sys_uart.h"
#include "sys_pd_config.h"
#include "sys_pd_hook.h"
#include "sys_reg.h"

volatile sys_uart_info_t g_sys_uart;


bool_t sys_uart_reg_read(unsigned char reg, unsigned char *p_val)
{
    timer_t timer;
    SYS_REG_SLA_DEV_ID_t dev = {1, 0, SYS_SLA_DEV_ID};

    timer_start(20000U, &timer);
    while (drv_uart_common_rx_available(drv_uart_second_get()) || g_sys_uart.rx_data_index)
    {
        sys_uart_handler((int)DRV_REG_GET(UART_PBR_REG+g_uart_addr_offset_map[drv_uart_second_get()]));
        if (timer_expired(&timer))
        {
            break;
        }
    }
    g_sys_uart.rx_data_index = 0;
 
    drv_uart1_putbyte(*(unsigned char *)(&dev));
    drv_uart1_putbyte(reg);

    timer_start(SYS_UART_TIMEOUT, &timer);
    do
    {
        if (drv_uart1_getbyte((u8_t *)&g_sys_uart.rx_data[g_sys_uart.rx_data_index]))
        {
            g_sys_uart.rx_data_index++;
        }
    } 
    while (!timer_expired(&timer) && (g_sys_uart.rx_data_index < (SYS_UART_REG_CTRL_HEAD_SIZE + 1)));

    if (!timer_expired(&timer))
    {
        if(g_sys_uart.rx_data[0] == (*(unsigned char *)(&dev)) )
        {
            *p_val = g_sys_uart.rx_data[SYS_UART_REG_OFFSET+1];
        }
        else
        {
            //

        }
        
        g_sys_uart.read_reg_miss_cnt = 0;
        g_sys_uart.rx_data_index = 0;
        return TRUE;
    }
    g_sys_uart.rx_data_index = 0;
    g_sys_uart.read_reg_miss_cnt++;
    if (g_sys_uart.read_reg_miss_cnt >= SYS_UART_REG_READ_MISS_MAX_CNT)
    {
#if CLI_ENABLED
        if (sys_cfg_dbg_get()) printf("\nReset(2)\n");
#endif /* CLI_ENABLED */
        //drv_chip_reset();
    }
    return FALSE;
}

bool_t sys_uart_reg_mread(unsigned char reg, int num, unsigned char *p_val)
{
    timer_t timer;
    SYS_REG_SLA_DEV_ID_t dev = {1, 1, SYS_SLA_DEV_ID};

    timer_start(20000U, &timer);
    while (drv_uart_common_rx_available(drv_uart_second_get()) || g_sys_uart.rx_data_index)
    {
        sys_uart_handler((int)DRV_REG_GET(UART_PBR_REG+g_uart_addr_offset_map[drv_uart_second_get()]));
        if (timer_expired(&timer))
        {
            break;
        }
    }

    g_sys_uart.rx_data_index = 0;
 
    drv_uart1_putbyte(*(unsigned char *)(&dev));
    drv_uart1_putbyte(num);
    drv_uart1_putbyte(reg);

    timer_start(SYS_UART_TIMEOUT_L, &timer);
    do
    {
        if (drv_uart1_getbyte((u8_t *)&g_sys_uart.rx_data[g_sys_uart.rx_data_index]))
        {
            g_sys_uart.rx_data_index++;
        }
    } 
    while (!timer_expired(&timer) && (g_sys_uart.rx_data_index < (SYS_UART_REG_CTRL_HEAD_SIZE_L + num)));

    if (!timer_expired(&timer))
    {
        if(g_sys_uart.rx_data[0] == (*(unsigned char *)(&dev)))
        {
            memcpy(p_val, (u8_t *)&g_sys_uart.rx_data[SYS_UART_REG_OFFSET_L+1], num);

        }
        else
        {
            //

        }
        g_sys_uart.read_reg_miss_cnt = 0;
        g_sys_uart.rx_data_index = 0;
        return TRUE;
    }
    g_sys_uart.rx_data_index = 0;
    g_sys_uart.read_reg_miss_cnt++;
    if (g_sys_uart.read_reg_miss_cnt >= SYS_UART_REG_READ_MISS_MAX_CNT)
    {
#if CLI_ENABLED
        if (sys_cfg_dbg_get()) printf("\nReset(3)\n");
#endif /* CLI_ENABLED */
        //drv_chip_reset();
    }
    return FALSE;
}

bool_t sys_uart_reg_write(unsigned char reg, unsigned char *p_val)
{
    SYS_REG_SLA_DEV_ID_t dev = {0, 0, SYS_SLA_DEV_ID};
    drv_uart1_putbyte(*(unsigned char *)(&dev));
    drv_uart1_putbyte(reg);
    drv_uart1_putbyte(*p_val);
    return TRUE;
}

bool_t sys_uart_reg_mwrite(unsigned char reg, int num, unsigned char *p_val)
{
    SYS_REG_SLA_DEV_ID_t dev = {0, 1, SYS_SLA_DEV_ID};
    drv_uart1_putbyte(*(unsigned char *)(&dev));
    drv_uart1_putbyte(num);
    drv_uart1_putbyte(reg);
    do 
    {
        --num;
        drv_uart1_putbyte(*p_val++);
    }
    while (num > 0);
    return TRUE;
}


void sys_uart_handler(int input)
{
    if (g_sys_uart.rx_data_index >= SYS_UART_BUFFER_SIZE)
    {
        goto rx_reset;
    }

    g_sys_uart.rx_data[g_sys_uart.rx_data_index++] = input;
    
    if (g_sys_uart.rx_data_index >= SYS_UART_REG_CTRL_HEAD_SIZE)
    {
        SYS_REG_SLA_DEV_ID_t *p_dev = (SYS_REG_SLA_DEV_ID_t *)(&g_sys_uart.rx_data[SYS_UART_REG_DEV_ID_OFFSET]);
        // invalid slave device ID
        if (p_dev->dev_id != SYS_SLA_DEV_ID)
            goto rx_reset;

        if (p_dev->cont_opr)
        {
            if (!p_dev->read)
            {
                // If received bytes less than REG NUM + 3, continue waiting byte
                if (g_sys_uart.rx_data_index < (g_sys_uart.rx_data[SYS_UART_REG_NUM_OFFSET] + SYS_UART_REG_CTRL_HEAD_SIZE_L))
                {
                    return;
                }

                for (int pos = 0; pos < g_sys_uart.rx_data[SYS_UART_REG_NUM_OFFSET]; pos++)
                {
                    // parsing event register only
                    if (SYS_UPD1_STAS_REG == g_sys_uart.rx_data[SYS_UART_REG_OFFSET_L]+pos)
                    {
                        g_sys_pd_info.upd1_sta = *(SYS_UPD_STA_REG_t *)&g_sys_uart.rx_data[SYS_UART_REG_OFFSET_L + 1 + pos];
                    }
                    else if (SYS_UPD2_STAS_REG == g_sys_uart.rx_data[SYS_UART_REG_OFFSET_L]+pos)
                    {
                        g_sys_pd_info.upd2_sta = *(SYS_UPD_STA_REG_t *)&g_sys_uart.rx_data[SYS_UART_REG_OFFSET_L + 1 + pos];
                    }
                }
            }
            goto rx_reset;
        }
        else 
        {
            if (!p_dev->read)
            {
                // If received bytes less than SYS_UART_REG_CTRL_HEAD_SIZE+1, continue waiting byte
                if (g_sys_uart.rx_data_index < (SYS_UART_REG_CTRL_HEAD_SIZE+1))
                {
                    return;
                }

                // parsing event register only
                if (SYS_UPD1_STAS_REG == g_sys_uart.rx_data[SYS_UART_REG_OFFSET])
                {
                    g_sys_pd_info.upd1_sta = *(SYS_UPD_STA_REG_t *)&g_sys_uart.rx_data[SYS_UART_REG_OFFSET + 1];
                }
                else if (SYS_UPD2_STAS_REG == g_sys_uart.rx_data[SYS_UART_REG_OFFSET])
                {
                    g_sys_pd_info.upd2_sta = *(SYS_UPD_STA_REG_t *)&g_sys_uart.rx_data[SYS_UART_REG_OFFSET + 1];
                }
            }
            goto rx_reset;
        }

        if (!g_sys_uart.rx_start_time)
            g_sys_uart.rx_start_time = now();

        if ((g_sys_uart.rx_start_time) && 
            (u32_t)(now() > g_sys_uart.rx_start_time) && 
            ((u32_t)(now() - g_sys_uart.rx_start_time) > SYS_UART_TIMEOUT))
        {
            goto rx_reset;
        }
    }
    return;

rx_reset:
#if CLI_ENABLED
    if ((sys_cfg_dbg_get() >= SYS_DEBUG_LEVEL_3) &&
        (g_sys_uart.rx_data_index))
    {
        drv_uart_puts("\nRX");
        drv_uart_puthex((u8_t *)&g_sys_uart.rx_data[0],g_sys_uart.rx_data_index,FALSE);
    }
#endif /* CLI_ENABLED */
    g_sys_uart.rx_data_index = 0;
    g_sys_uart.rx_start_time = 0;
    //memset((u8_t *)&g_sys_uart.rx_data[0],0,40);
}

void sys_uart_polling(u32_t uart_id)
{
    if (drv_uart_common_rx_available(uart_id))
    {
        sys_uart_handler((int)DRV_REG_GET(UART_PBR_REG+g_uart_addr_offset_map[uart_id]));
    }
}

