#include "../../../User/includes.h"
#include "device.h"
#include "net_proc.h"

#include "radio.h"
#include "project_config.h"
#include "stdio.h"
#include "stm32f10x_it.h"
#include "delay.h"
#include "string.h"
#include "../../gateway_collect/gateway_collect.h"
#include "../../globalDef.h"
#include "lora.h"

extern volatile uint32_t TickCounter;
loraParam g_loraPa[4];
#define RADIO_RX_TIMEOUT_VALUE		0
//uint8_t cmpBuf[256] ;
uint8_t lora_state = 0;
OS_Q  lora_q;


system_lora_t sys_loraTX;
system_lora_t sys_loraRx;

uint8_t g_loraCadStatus = 0;
uint8_t g_loraCadCount = 0;
uint32_t g_cadTick = 0;
uint32_t g_cadTickTime = 0;
/*!
 * Radio events function pointer
 * 这个是传参进入其他函数中了，所以用全局变量(局部变量使用完了内存释放可能导致异常)
 */
static RadioEvents_t RadioEventsObj;
static void SX126xOnCadDone( bool channelActivityDetected );
static void SX126xConfigureCad( RadioLoRaCadSymbols_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin , uint32_t cadTimeout);

void * lora_queue_mem_calloc_must(void)
{
    OS_ERR      err;
    void * p_msg = NULL;

    OSSemPend(&sys_loraTX.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
    p_msg = OSMemGet(&sys_loraTX.lora_m, &err);
  //  printf("\r\n~~~~~~~~~~~~~~~err = %d\r\n",err);
    OSSemPost(&sys_loraTX.sem, OS_OPT_POST_ALL, &err);
//	printf("\r\n~~~~~~~~~~~~~~~err = %d  end  \r\n",err);
    return p_msg;
}

int lora_queue_mem_free(void * p_msg)
{
    OS_ERR      err;

    OSSemPend(&sys_loraTX.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
    OSMemPut(&sys_loraTX.lora_m, p_msg, &err);
    OSSemPost(&sys_loraTX.sem, OS_OPT_POST_ALL, &err);

    return err;
}

void lora_queue_insert(char *p_msg, uint32_t msg_len)
{
    OS_ERR      err;

    OSSemPend(&sys_loraTX.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
    OS_QPost(&sys_loraTX.lora_q, p_msg, msg_len, OS_OPT_POST_FIFO, 0, &err);
    OSSemPost(&sys_loraTX.sem, OS_OPT_POST_ALL, &err);

    //printf("net_queue_insert %p %d\r\n", p_msg, msg_len);
}

void * lora_queue_mem_calloc_mustRx(void)
{
    OS_ERR      err;
    void * p_msg = NULL;

    OSSemPend(&sys_loraRx.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
    p_msg = OSMemGet(&sys_loraRx.lora_m, &err);
    OSSemPost(&sys_loraRx.sem, OS_OPT_POST_ALL, &err);
    return p_msg;
}

int lora_queue_mem_freeRx(void * p_msg)
{
    OS_ERR      err;

    OSSemPend(&sys_loraRx.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
    OSMemPut(&sys_loraRx.lora_m, p_msg, &err);
    OSSemPost(&sys_loraRx.sem, OS_OPT_POST_ALL, &err);
    return err;
}

void lora_queue_insertRx(char *p_msg, uint32_t msg_len)
{
    OS_ERR      err;

    OSSemPend(&sys_loraRx.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
    OS_QPost(&sys_loraRx.lora_q, p_msg, msg_len, OS_OPT_POST_FIFO, 0, &err);
    OSSemPost(&sys_loraRx.sem, OS_OPT_POST_ALL, &err);
    //printf("net_queue_insert %p %d\r\n", p_msg, msg_len);
}
static void SX126xOnTxDone( void )
{
	//printf("TxDone\r\n");
	Radio.Standby();
	lora_state = lora_state_idle;
  g_loraCadStatus = 0;

	//Radio.Rx( RADIO_RX_TIMEOUT_VALUE );
}
/*lora数据接收 2021.11.08*/
static void SX126xOnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
	OS_ERR      err;
	
//	inner_msg_format_t *p_msg = NULL;
	char *p_msg = NULL;
        // rssi:信号强度
//	printf("RxDone size:%d <rssi:%d, snr:%d> \r\n",size, rssi, snr);	
	Radio.Standby();
//	p_msg = (gateway_collect_com_t *)payload;
        g_runData.rssi_lora = rssi+1000;
        p_msg = lora_queue_mem_calloc_mustRx();
	if(p_msg) 
	{
            if(size) //和上次数据不同，数据有效
            {
               // data_dump("LORA Rxtx", (uint8_t *)payload, size);
                memcpy(p_msg, payload, size);//&&memcmp(cmpBuf, payload, size)
                lora_queue_insertRx((char *)p_msg, size);
            } else {
                lora_queue_mem_freeRx(p_msg);
            }
  //              printf("lora rcv\r\n");

	}
	g_loraCadStatus = 0;
//	OS_QPost(&lora_q, payload, size, OS_OPT_POST_FIFO, 0, &err);
//	data_dump("LORA Rx", payload, size);
#if 0
	if(((p_msg->type <= net_msg_type_debug)||
		(p_msg->type == net_msg_type_bind_req)||
		(p_msg->type == net_msg_type_node_echo))&&
		(device_type_get() != DEV_TYPE_GATEWAY)) {/* 节点丢弃 */
		//drop packets;
	} else if(((p_msg->type == net_msg_type_bind_rsp)||
		(p_msg->type == net_msg_type_gw_echo))&&
		(device_type_get() == DEV_TYPE_GATEWAY)) {
		//drop packets;
	} else {
		data_dump("LORA Rx", payload, size);
		//Radio.Rx( RADIO_RX_TIMEOUT_VALUE );
		if(((p_msg->type&0x10) == 0x10)||
			((p_msg->type&0x20) == 0x20)) {
			p_msg = (inner_msg_format_t *)net_queue_mem_calloc_must();
		} else {
			p_msg = (inner_msg_format_t *)net_queue_mem_calloc();
		}
		if(p_msg) {
			if(size) {//和上次数据不同，数据有效
//				data_dump("LORA Rxtx", (uint8_t *)p_msg, size);
				memcpy(p_msg, payload, size);//&&memcmp(cmpBuf, payload, size)
				net_queue_insert((char *)p_msg, size);
			} else {
				net_queue_mem_free(p_msg);
			}
		}
	}
#endif
	lora_state = lora_state_idle;
}

static void SX126xOnCadDone( bool channelActivityDetected )
{
    inner_msg_format_t *p_msg = NULL;
    OS_MSG_SIZE msg_len = 0;
    OS_ERR      err;
    int a = 0;

  //  __disable_irq();
    Radio.Standby();
  //  printf("cadDone %d\r\n", channelActivityDetected);
    if(channelActivityDetected==true){
       // lora_state = lora_state_idle;
        g_loraCadStatus = 0;
        g_loraCadCount++;
        srand(TickCounter);
        a = rand() % 50;
        if(g_runData.bUpdateHost == 0)g_cadTickTime = 300+a;
        else {
            if(g_runData.bUpdate != 0) {
                g_cadTickTime = 700;
            }
            else g_cadTickTime = 300+a;
        }
        g_cadTick = TickCounter;
        lora_state = lora_state_sendRept;
    }
    else {
        lora_queue_proc_testTx();
        g_loraCadCount = 0;
        g_cadTick = TickCounter;

    }
   //  __enable_irq();
    return ;
}

static void SX126xOnTxTimeout( void )
{
	printf("TxTimeout\r\n");
	Radio.Standby();
	lora_state = lora_state_idle;
}

static void SX126xOnRxTimeout( void )
{
	printf("RxTimeout retry recive\r\n");
	Radio.Standby();
	//Radio.Rx( LORA_RX_TIMEOUT_VALUE ); 
	lora_state = lora_state_idle;
}

static void SX126xOnRxError( void )
{
	printf("RxError retry recive\r\n");
	Radio.Standby();
	//Radio.Rx(LORA_RX_TIMEOUT_VALUE); 
	lora_state = lora_state_idle;
}
static void SX126xConfigureCad( RadioLoRaCadSymbols_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin , uint32_t cadTimeout)
{
    SX126xSetDioIrqParams( 	IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED, IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED,
                            IRQ_RADIO_NONE, IRQ_RADIO_NONE );
    SX126xSetCadParams( cadSymbolNum, cadDetPeak, cadDetMin, LORA_CAD_ONLY, ((cadTimeout * 1000) / 15.625 ));
}
void lora_send(char *tx_data, uint32_t tx_len)
{
	char *p_msg = NULL;
	OS_ERR      err;		
	p_msg = (char *)lora_queue_mem_calloc_must();	
	if(p_msg) {
		memcpy(p_msg, tx_data, tx_len);
		lora_queue_insert((char *)p_msg, tx_len);
	}
	else
	{
		lora_queue_mem_free(p_msg);
	}
//	char *p_msg = NULL;
//	OS_ERR      err;	

//	/* 接受消息, 发往net_proc模块统一处理 */
//	p_msg = (char *)net_queue_mem_calloc_must();	
//	if(p_msg) {
//		memcpy(p_msg, tx_data, tx_len);		
//		OS_QPost(&lora_q, p_msg, tx_len, OS_OPT_POST_FIFO, 0, &err);
//	}
}

void lora_net_send_test(uint8_t *tx_data, uint8_t tx_len)
{
	if(tx_data[tx_len-2]==0x0d && tx_data[tx_len-1]==0x0a)
	{
		tx_data[tx_len-2]='\0';
		tx_data[tx_len-1]='\0';
		tx_len-=2;
		data_dump("lora tx:", tx_data, tx_len);
	}
	AIR_MQTT_PUB((char*)g_upLinkTopic,tx_data,0);
}
/*lora 发送消息 */
void lora_send_test(uint8_t *buf, uint8_t size)
{
    gateway_collect_com_t *msg = (gateway_collect_com_t*)msg;

//    if(msg->type==0x56){
//        downlink_config.collect_conf[msg->taxinfo.comdata.coll_no].coll_send_num++;
//    }
//    if(g_runData.bUpdate==0){
//        if(msg->type==0x57){
//            set_led_status(msg->taxinfo.data.coll_no,0);
//        }
//        else {
//            set_led_status(msg->taxinfo.info[4],0);
//        }
//    }
    Radio.Send(buf, size);
}

void lora_queue_proc_test(void)
{
    OS_ERR      err;
    gateway_collect_com_t *p_msg;
    OS_MSG_SIZE msg_len;
    uint32_t a = 0;
    uint16_t crc = 0, fcrc = 0;

    OSSemPend(&sys_loraRx.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
    p_msg = (gateway_collect_com_t *)OSQPend(&sys_loraRx.lora_q, 0, OS_OPT_PEND_NON_BLOCKING, &msg_len, NULL, &err);	/* blocking. */
    OSSemPost(&sys_loraRx.sem, OS_OPT_POST_ALL, &err);

    if(p_msg&&msg_len)
    {

        if(p_msg->frame_header != 0xfefe){
            lora_queue_mem_freeRx(p_msg);
            return;
        }
        crc = _crc16_get((uint8_t*)p_msg,p_msg->len+GATE_COLL_HEAD_LEN-2);// len-2);
        fcrc = p_msg->taxinfo.info[p_msg->len-1];// data[p_tax_tx->len+GATE_COLL_HEAD_LEN-1];
        fcrc = (fcrc<<8)| p_msg->taxinfo.info[p_msg->len-2];//data[p_tax_tx->len+GATE_COLL_HEAD_LEN-2];
        if(fcrc != crc ){//校验位不对则返回
             printf("lora_queue_proc: crc error\r\n");
             //data_dump("rcv updata", (uint8_t *)p_msg, p_msg->len + 12);
             lora_queue_mem_freeRx(p_msg);
            return;
        }
        switch(p_msg->type){
        case COLL_GATE_TAX_QUERY: //0x67业务数据接收接收消息
           
            break;
        case COLL_GATE_HEART_QUERY:	//0x66网关与采集器的上行心跳包
            
            break;
        case COLL_GATE_FIRMMSG_QUERY://0x68采集器上发固件信息
            
            break;
        case 0x22: // 升级重新传指令， 采集器上发的指令
            printf("\r\n 收到0x22指令\r\n");
            g_runData.repeatUpdateTime = TickCounter;
            g_runData.readUpdateStatusTime = 0;
            if(g_runData.bUpdateHost == 0) break;
            lora_gw_ota_proc(&sys_net, p_msg);
            break;
       case 0x23: // 升级成功，主设备接收从设备的上报指令
            printf("rcv 0x23 cmd ,delay = %d\r\n",a);
            if(g_runData.bResetUpdate == 2) { // 从设备时，
                srand(TickCounter);
                a = rand() % 233+200;
                timeout_setValue(&g_updateProg.upStatusOut,a);
                timeout_start(&g_updateProg.upStatusOut);
            }
            else if(g_runData.bResetUpdate == 0) // 主设备
                gateway_update_status_rcv(p_msg,msg_len);
            break;
        case 0x16: // 通知采集器升级

            break;
        case net_msg_type_update_start: // 网关升级网关指令开始0x13
             printf("\r\n 收到0x13指令\r\n");
             gateway_lora_ota_proc(p_msg);
             break;
        case net_msg_type_update_continues: // 0x14指令
            printf("\r\n 收到0x14指令\r\n");
            gateway_lora_ota_proc(p_msg);
            break;
        case net_msg_type_update_retransmit_rsp: // 0x15指令
            printf("\r\n 收到0x15指令\r\n");
            gateway_lora_ota_proc(p_msg);
            break;
        default:
            break;
        }
        lora_queue_mem_freeRx(p_msg);
    }
}

void lora_queue_proc_testTx(void)
{
    OS_ERR      err;
    gateway_collect_com_t *p_msg;
    OS_MSG_SIZE msg_len;
    uint8_t coll = 0;

  //  printf("net_queue_proc 1111\r\n");
    OSSemPend(&sys_loraTX.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
    p_msg = (gateway_collect_com_t *)OSQPend(&sys_loraTX.lora_q, 0, OS_OPT_PEND_NON_BLOCKING, &msg_len, NULL, &err);	/* blocking. */
    OSSemPost(&sys_loraTX.sem, OS_OPT_POST_ALL, &err);
    if(p_msg&&msg_len)
    {
        if(p_msg->type == 0x57) coll = p_msg->taxinfo.data.coll_no;
        else coll = p_msg->taxinfo.info[4];
        printf("++++++++++ msg type = 0x%x   coll = %d +++++\r\n",p_msg->type,coll);
        lora_send_test((uint8_t *)p_msg, msg_len);
        lora_queue_mem_free(p_msg);
        if(device_fixed_info.Work_State == DEV_WORK_STATE_OTA_RETRANSMIT)
        {
            ota_retransmit_delay.timeout = OTA_CAD_FREE_DELAYTIME;
            ota_retransmit_delay.counter = TickCounter;
            ota_continuous_end_flag = OTA_CONTINUOUS_DELAY;
        }

       // printf("发送loraSend = %d,采集器(%d):发送:%d\r\n",g_loraCollMsg.lora_sendCount,p_msg->taxinfo.info[4],g_loraCollMsg.info[p_msg->taxinfo.info[4]].sendNum);
    }
    else {
        lora_state = lora_state_idle;
     //   printf("\r\n lora state idel 11111111 \r\n");
    }
}


void lora_task(void)
{
    //inner_msg_format_t *p_msg = NULL;
    OS_MSG_SIZE msg_len = 0;
    OS_ERR      err;
    uint32_t i = 0;
    /* 发送消息 */

    if(g_runData.bUpdate ==0 ) {
        if(g_runData.loraConnectTime == 0) return;
        if(g_runData.loraConnectTime >30) { // 半个小后，lora不再接收数据

            g_runData.loraConnectTime = 0;
            SX126xReset();
            printf("lora reset \r\n ");
        }
    }


    lora_queue_proc_test();

    switch(lora_state) {
    case lora_state_idle: //idle
        Radio.Standby();
        Radio.Rx( LORA_RX_TIMEOUT_VALUE );
        lora_state = lora_state_send;// lora_state_rcv;
//        printf("lora rx state\n");
    case lora_state_rcv:
      //  lora_queue_proc_test();
      //  lora_state = lora_state_send;
        break;
    case lora_state_send:
        if(sys_loraTX.lora_q.MsgQ.NbrEntries >0){ //除列不为空
            Radio.Standby();
            Radio.StartCad();
            lora_state = lora_state_max;
            break;
        }
      //  lora_state = lora_state_rcv;
        break;
    case lora_state_sendRept:
        if(g_loraCadCount>0) {
            if(TickCounter - g_cadTick>=g_cadTickTime){
                Radio.Standby();
                Radio.StartCad();
                g_cadTick = TickCounter;
                printf("\r\n&&&&&&& timer out \r\n");
            }
            if(g_loraCadCount>1){
                lora_queue_proc_testTx();
                g_loraCadCount = 0;
                printf("\r\n ^^^^^^2 count  \r\n");

            }
        }
        break;
    case lora_state_max:
        break;
    default:

        break;
    }

    Radio.IrqProcess( );
}



void lora_init(char *device_id)
{
	OS_ERR      err;	
	
	
    OSSemCreate(&sys_loraTX.sem, "lora_sem", 1, &err);//创建信号量
    OSQCreate(&sys_loraTX.lora_q, "lora_queue", 8, &err);//创建网络消息处理队列
    OSMemCreate(&sys_loraTX.lora_m, "lora_memory", sys_loraTX.memory, 8, 256, &err);//创建内存管理池
	
	OSSemCreate(&sys_loraRx.sem, "lora_semRx", 1, &err);//创建信号量
    OSQCreate(&sys_loraRx.lora_q, "lora_queueRx", 8, &err);//创建网络消息处理队列
    OSMemCreate(&sys_loraRx.lora_m, "lora_memoryRx", sys_loraRx.memory, 8, 256, &err);//创建内存管理池
	
	
	RadioEventsObj.TxDone = SX126xOnTxDone;
	RadioEventsObj.RxDone = SX126xOnRxDone;
	RadioEventsObj.TxTimeout = SX126xOnTxTimeout;
	RadioEventsObj.RxTimeout = SX126xOnRxTimeout;
	RadioEventsObj.RxError = SX126xOnRxError;
	RadioEventsObj.CadDone = SX126xOnCadDone;

    
	Radio.Init( &RadioEventsObj );
	Radio.SetChannel(LORA_FRE);
	Radio.SetTxConfig( MODEM_LORA, LORA_TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                     LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                     LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                     true, 0, 0, LORA_IQ_INVERSION_ON, 5000 );//参数：lora模式,发射功率,fsk用的lora设置为0就可以，带宽，纠错编码率，前导码长度，固定长度数据包(一般是不固定的所以选false)，crc校验，0表示关闭跳频，跳频之间的符号数(关闭跳频这个参数没有意义)，这个应该是表示是否要翻转中断电平的，超时时间

	Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                     LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                     LORA_SX126X_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
                     0, true, 0, 0, LORA_IQ_INVERSION_ON, false );
//	Radio.Rx( LORA_RX_TIMEOUT_VALUE );

// Radio.SetTxConfig( MODEM_LORA, LORA_TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
//                                   LORA_SPREADING_FACTOR, LORA_CODINGRATE,
//                                   LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
//                                   true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );

//    Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
//                                   LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
//                                   LORA_TX_OUTPUT_POWER, LORA_FIX_LENGTH_PAYLOAD_ON,
//                                   0, true, 0, 0, LORA_IQ_INVERSION_ON, true );
//	
    SX126xConfigureCad( CAD_SYMBOL_NUM, CAD_DET_PEAK,CAD_DET_MIN, CAD_TIMEOUT_MS);
    Radio.StartCad();
    lora_state = lora_state_rcv;
    g_runData.loraConnectTime = 1;
	return;
}
