
#include "interruptSend.h"
#include "bl_usart.h"


#define RS485_MAX_PACK_DATA_LEN  256

static uint8_t dataLocation1[RS485_MAX_PACK_DATA_LEN];
static uint8_t dataLocation2[RS485_MAX_PACK_DATA_LEN];
static uint8_t dataLocation3[RS485_MAX_PACK_DATA_LEN];

extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;

#define GW485_huart huart2
#define BAT485_huart huart3

/* 指定对齐方式为1字节 */
#pragma pack(push,1)

typedef struct _send_data_info{
    device_handle device;
    BOOL dataState;             //储存数据的状态，TRUE：有数据，FALSE：无数据
    uint8_t dataLen;            //数据长度
    uint8_t Counter;            //已经发送的长度
    uint8_t *data;              //储存数据的内容
}send_data_info;

typedef struct _uart_send_info {
    uint8_t insertState;                    //能否插入指示，大于0代表能插入
    // uint8_t sendStateGw:1;                  //能否发送指示，1：需要发送，0：不需要发送
    // uint8_t sendStateBat:1;                 //能否发送指示
    // uint8_t sendOverStateGw:1;              //发送完成指示，1：发送完成，0：发送中
    // uint8_t sendOverStateBat:1;             //发送完成指示
    // uint8_t GwState:1;                      //向上通信485总线空闲状态，1：空闲，0：繁忙
    // uint8_t idleStateGw:1;                  //向上通信空闲状态，1：没数据到来，0：有数据到来
    // uint8_t BatState:1;                     //向下通信485总线空闲状态
    // uint8_t idleStateBat:1;                 //向下通信空闲状态

    BOOL sendStateGw;                       //能否发送指示，TRUE：需要发送，FALSE：不需要发送
    BOOL sendStateBat;                      //能否发送指示
    BOOL sendOverStateGw;                   //发送完成指示，TRUE：发送完成，FALSE：发送中
    BOOL sendOverStateBat;                  //发送完成指示
    BOOL GwState;                           //向上通信485总线空闲状态，TRUE：空闲，FALSE：繁忙
    BOOL idleStateGw;                       //向上通信空闲状态，TRUE：没数据到来，FALSE：有数据到来
    BOOL BatState;                          //向下通信485总线空闲状态
    BOOL idleStateBat;                      //向下通信空闲状态

    send_data_info *insertData;             //通过该指针写入数据
    send_data_info *sendDataGw;             //通过该指针发送数据
    send_data_info *sendDataBat;            //通过该指针发送数据
    send_data_info data1;                   //储存数据的第1个位置
    send_data_info data2;                   //储存数据的第2个位置
    send_data_info data3;                   //储存数据的第3个位置
}uart_send_info;
/* 恢复默认的对齐设置 */
#pragma pack(pop)

uart_send_info uart_send = {0};

/**
  * @brief  串口中断发送的初始化，通过空闲中断来判断总线空闲状态
  * @param
  * @retval
  *
  */
void send_init(void)
{
    /* 指定数据储存位置 */
    uart_send.data1.data = dataLocation1;
    uart_send.data2.data = dataLocation2;
    uart_send.data3.data = dataLocation3;

    /* 初始化插入位置为data1 */
    uart_send.insertData = &uart_send.data1;
    uart_send.sendDataGw = NULL;
    uart_send.sendDataBat = NULL;

    //有3个位置可以写入数据
    uart_send.insertState = 3;

    //没有数据能够发送
    uart_send.sendStateGw = FALSE;
    uart_send.sendStateBat = FALSE;

    //发送完成
    uart_send.sendOverStateBat = TRUE;
    uart_send.sendOverStateGw = TRUE;

    //485总线空闲
    uart_send.GwState = TRUE;
    uart_send.idleStateGw = TRUE;
    uart_send.BatState = TRUE;
    uart_send.idleStateBat = TRUE;
}

/**
  * @brief  GW485串口接收到数据后调用该函数，设置485总线空闲状态
  * @param
  * @retval
  *
  */
void setIdleStateGw(void)
{
    if (uart_send.idleStateGw == FALSE) {
        uart_send.idleStateGw = TRUE;
    }
}

/**
  * @brief  BAT485串口接收到数据后调用该函数，设置485总线空闲状态
  * @param
  * @retval
  *
  */
void setIdleStateBat(void)
{
    if (uart_send.idleStateBat == FALSE) {
        uart_send.idleStateBat = TRUE;
    }
}

/**
  * @brief   GW485串口设置485总线空闲状态,间隔10ms使用
  * @param
  * @retval
  *
  */
void setGwState(void)
{
    if (uart_send.idleStateGw == FALSE) {
        uart_send.GwState = TRUE;
    } else {
        uart_send.GwState = FALSE;
    }

    uart_send.idleStateGw = FALSE;
}


/**
  * @brief   BAT485串口设置485总线空闲状态,间隔10ms使用
  * @param
  * @retval
  *
  */
void setBatState(void)
{
    if (uart_send.idleStateBat == FALSE) {
        uart_send.BatState = TRUE;
    } else {
        uart_send.BatState = FALSE;
    }

    uart_send.idleStateBat = FALSE;
}

/**
  * @brief   GW485串口发送完成后，调用该函数
  * @param
  * @retval
  *
  */
void setSendOverStateGw(void)
{
    /* 配置文件传输完成，复位 */
    if (uart_send.sendDataGw->data[9] = 0xD0
        && uart_send.sendDataGw->data[12] == 0xAA) {
        NVIC_SystemReset();
    }
    
#ifdef HY_ChargeControlBox_PROTOCOL_ENABLE
    /* HY，复位指令 */
    if (uart_send.sendDataGw->data[11] = 0x66
        && uart_send.sendDataGw->data[14] == 0xFF) {
        NVIC_SystemReset();
    }
#endif
    
    uart_send.sendOverStateGw = TRUE;
    uart_send.sendStateGw = FALSE;
    uart_send.sendDataGw->dataState = FALSE;
    uart_send.sendDataGw = NULL;
    uart_send.insertState++;

    /* 插入指针指向为空时 */
    if (uart_send.data1.dataState == FALSE) {
        uart_send.insertData = &uart_send.data1;
    }
    else if (uart_send.data2.dataState == FALSE) {
        uart_send.insertData = &uart_send.data2;
    }
    else if (uart_send.data3.dataState == FALSE) {
        uart_send.insertData = &uart_send.data3;
    }
}

/**
  * @brief   BAT485串口发送完成后，调用该函数
  * @param
  * @retval
  *
  */
void setSendOverStateBat(void)
{
    uart_send.sendOverStateBat = TRUE;
    uart_send.sendStateBat = FALSE;
    uart_send.sendDataBat->dataState = FALSE;
    uart_send.sendDataBat = NULL;
    uart_send.insertState++;    

    /* 插入指针指向为空时 */
    if (uart_send.data1.dataState == FALSE) {
        uart_send.insertData = &uart_send.data1;
    }
    else if (uart_send.data2.dataState == FALSE) {
        uart_send.insertData = &uart_send.data2;
    }
    else if (uart_send.data3.dataState == FALSE) {
        uart_send.insertData = &uart_send.data3;
    }
}

/**
  * @brief   检测是否有数据需要发送
  * @param
  * @retval 
  *
  */
void check_sendState(void)
{
    /* 向上通信总线空闲时，检测到有数据需要发送，同时上一次数据发送完成 */
    if (uart_send.GwState && uart_send.sendStateGw && uart_send.sendOverStateGw) {
        /* 将数据塞入中断发送 */
        HAL_UART_Transmit_IT(&GW485_huart, uart_send.sendDataGw->data, uart_send.sendDataGw->dataLen);
        uart_send.sendOverStateGw = FALSE;
    }
    
    /* 向下通信总线空闲时，检测到有数据需要发送，同时上一次数据发送完成 */
    if (uart_send.BatState && uart_send.sendStateBat && uart_send.sendOverStateBat) {
        HAL_UART_Transmit_IT(&BAT485_huart, uart_send.sendDataBat->data, uart_send.sendDataBat->dataLen);
        uart_send.sendOverStateBat = FALSE;
    }

    if (uart_send.sendDataGw == NULL) {
        if (uart_send.data1.dataState) {
            if (uart_send.data1.device == g_gw485_uart2_handle) {
                uart_send.sendStateGw = TRUE;
                uart_send.sendDataGw = &uart_send.data1;
            }
        }
        if (uart_send.data2.dataState) {
            if (uart_send.data2.device == g_gw485_uart2_handle) {
                uart_send.sendStateGw= TRUE;
                uart_send.sendDataGw = &uart_send.data2;
            }
        }
        if (uart_send.data3.dataState) {
            if (uart_send.data3.device == g_gw485_uart2_handle) {
                uart_send.sendStateGw = TRUE;
                uart_send.sendDataGw = &uart_send.data3;
            }
        }
    }
    
    if (uart_send.sendDataBat == NULL) {
        if (uart_send.data1.dataState) {
            if (uart_send.data1.device == g_bat485_uart3_handle) {
                uart_send.sendStateBat = TRUE;
                uart_send.sendDataBat = &uart_send.data1;
            }
        }
        if (uart_send.data2.dataState) {
            if (uart_send.data2.device == g_bat485_uart3_handle) {
                uart_send.sendStateBat= TRUE;
                uart_send.sendDataBat = &uart_send.data2;
            }
        }
        if (uart_send.data3.dataState) {
            if (uart_send.data3.device == g_bat485_uart3_handle) {
                uart_send.sendStateBat = TRUE;
                uart_send.sendDataBat = &uart_send.data3;
            }
        }        
    }
}

/**
  * @brief   串口中断发送函数
  * @param
  * @retval
  *
  */
void uart_interruptSend(device_handle device, uint8_t buff[], uint8_t len)
{
    /* 拷贝数据到发送 */
    do {
        if (uart_send.insertState > 0 && uart_send.insertData != NULL) {
//            memcpy(uart_send.insertData->data, buff, len);
            for (int var = 0; var < len; ++var) {
                uart_send.insertData->data[var] = buff[var];
//                printf(" %x ", uart_send.insertData->data[var]);
            }
            uart_send.insertData->Counter = 0;
            uart_send.insertData->dataLen = len;
            uart_send.insertData->device = device;
//            uart_send.insertData->dataState = 1;
//            uart_send.insertState--;

            uart_send.insertData->dataState = TRUE;
            uart_send.insertState--;
            break;
        }
    /* 0执行一次， 1一直循环直到能插入 */
    } while (0);

    /* 可插入数据大于0时，将插入指针指向空的储存位置,否则指向NULL */
    if (uart_send.insertState > 0) {
        if (uart_send.data1.dataState == FALSE) {
            uart_send.insertData = &uart_send.data1;
        }
        else if (uart_send.data2.dataState == FALSE) {
            uart_send.insertData = &uart_send.data2;
        }
        else if (uart_send.data3.dataState == FALSE) {
            uart_send.insertData = &uart_send.data3;
        }
    } else {
        uart_send.insertData = NULL;
    }
}


/**
  * @brief   得到中断发送插入数据指针
  * @param
  * @retval
  *
  */
uint8_t *getInsertData(void)
{
    return uart_send.insertData->data;
}


/**
  * @brief   将数据发送指针的内容发送
  * @param
  * @retval
  *
  */
void  uart_insertDataSend(device_handle device, uint8_t len)
{
    uart_send.insertData->Counter = 0;
    uart_send.insertData->dataLen = len;
    uart_send.insertData->device = device;

    uart_send.insertData->dataState = TRUE;
    uart_send.insertState--;

    /* 可插入数据大于0时，将插入指针指向空的储存位置,否则指向NULL */
    if (uart_send.insertState > 0) {
        if (uart_send.data1.dataState == FALSE) {
            uart_send.insertData = &uart_send.data1;
        }
        else if (uart_send.data2.dataState == FALSE) {
            uart_send.insertData = &uart_send.data2;
        }
        else if (uart_send.data3.dataState == FALSE) {
            uart_send.insertData = &uart_send.data3;
        }
    } else {
        uart_send.insertData = NULL;
    }
}