/* Includes ----------------------------------------------------------------- */
#include "module/mr16.h"

#include <main.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>

#include "bsp/flash.h"
#include "device/sx1281_driver/sx1281.h"
#include "usart.h"
#include "device/sx1281_driver/radio.h"
#include "device/lcd_driver/lcd.h"
#include "device/sx1281_driver/sx1281_driver.h"
#include "component/FreeRTOS_CLI.h"

#include "module/config.h"
/* USER INCLUDE BEGIN */

/* USER INCLUDE END */

/* Private define ----------------------------------------------------------- */
/* USER DEFINE BEGIN */

/* USER DEFINE END */

/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
typedef enum {
  MR16_FSM_NONE,
  MR16_FSM_INIT,
  MR16_FSM_TX,
  MR16_FSM_RX,
}MR16_FSM_t;

typedef enum {
  /* 设置主页 */
  MR16_SETTINGFSM_home,

  /*一*/
  MR16_SETTINGFSM_mode,
  /*二*/
  MR16_SETTINGFSM_RX_ID,
  /*三*/
  MR16_SETTINGFSM_radioParams,
  /*1*/
  MR16_SETTINGFSM_radioMode,
  /*2*/
  MR16_SETTINGFSM_modulationParams,
  /*3*/
  MR16_SETTINGFSM_packetParams,
  /*4*/
  MR16_SETTINGFSM_rfFrequency,
  /*5*/
  MR16_SETTINGFSM_txOutputPower,
  /*6*/
  MR16_SETTINGFSM_rampTime,
  /*7*/
  MR16_SETTINGFSM_baudrate,
}MR16_SettingFSM_t;
/* USER STRUCT BEGIN */

/* USER STRUCT END */

/* Private variables -------------------------------------------------------- */
/* USER VARIABLE BEGIN */

/* USER VARIABLE END */
SX1281_t radio;
//lcd点阵数组
extern const unsigned char logo_M[];
//串口接收数据及字长
extern uint8_t uart2_data[255],uart2_datalength;

uint8_t radioRXBuffer[BUFFER_SIZE];
uint8_t radioRXSize;

static MR16_FSM_t MR16_FSM = MR16_FSM_NONE;

static MR16_SettingFSM_t MR16_SettingFSM=MR16_SETTINGFSM_home;

extern MR16_t mr16;

int8_t MR16_CLI_Init();
/* Private function  -------------------------------------------------------- */
/* USER FUNCTION BEGIN */

/* USER FUNCTION END */
int a=0;
int8_t SX1281_Callback(SX1281_States_t source) {
  switch (source) {
    case RX_DONE:
        /* 打印状态 */
        printf( "\r\n[RX] >>> Packet Received <<<\r\n" );
        /* 从缓冲区拿数据 */
        radioRXSize = 0;
        Radio.GetPayload( radioRXBuffer, &radioRXSize, BUFFER_SIZE);
        radioRXBuffer[radioRXSize+1] = 0;
        uint16_t RXheader=(uint16_t)radioRXBuffer[1]<<8 & (uint16_t)radioRXBuffer[0];
        for (int i=0; i<3; i++) {
          if (RXheader==mr16.param->RX_ID[i]){ 
          mr16.packetCount[i]++;
          }
        }
        printf( "[RX] Header: 0x%04X | Size: %d bytes | Count: %d\r\n", 
                RXheader, radioRXSize, mr16.packetCount[0]+mr16.packetCount[1]+mr16.packetCount[2] );
      break;

    case RX_TIMEOUT:
        /* 打印状态 */
        printf( "\r\n[RX] ... Timeout (Restarting RX)\r\n" );
		SX1281_SetRXSuccessive(&radio);
      break;

    case RX_ERROR:
        /* 打印状态 */
        printf( "\r\n[RX] !!! ERROR - Reception Failed !!!\r\n" );
        Radio.SetRx( ( TickTime_t ) { RADIO_TICK_SIZE_1000_US, 0x1000 } );
      break;

    case TX_DONE:
        /* 打印状态 */
        printf( "\r\n[TX] <<< Packet Sent Successfully >>>\r\n" );
        printf( "[TX] Length: %d bytes\r\n", mr16.txbuffer[2]+5 ); 
//		radio.param.packetParams.Params.Flrc.PayloadLength = data_length;	
//		Radio.SetPacketParams( &radio.param.packetParams );
        // a++;if (a>100) a=0;
        // uint8_t haha[5]={a,2,3,4,a};
        // SX1281_SetTX(&radio,(uint8_t*)haha,5);
        SX1281_SetTX(&radio,mr16.txbuffer,mr16.txbuffer[2]+5);
		// SX1281_SetTX(uart_data,data_length);
      break;

    case TX_TIMEOUT:
        /* 打印状态 */
        printf( "\r\n[TX] !!! TIMEOUT - Transmission Failed !!!\r\n" ); 
        
      break;

    case LORA_CAD_DONE:
        /* 打印状态 */
        printf( "\r\n[CAD] Channel Activity Detected\r\n" );
      break;
    default:
      break;
  }
  return 0;  
}

/* Exported functions ------------------------------------------------------- */
int8_t MR16_UI_PowerON() {

    LCD_DrawBitmap(logo_M,180,80,64,64,CRIMSON,MSB);
}

int8_t MR16_UI_Home() {

}

int8_t MR16_UI_Setting() {

}

int8_t MR16_Init(MR16_t *mr16, MR16_Param_t *param, MR16_Mode_t mr16Mode, SX1281_RadioMode_t radioMode) {
  MR16_CLI_Init();
	
  mr16->param=param;
	///////////////////待解决flash和SX1281Init中默认参数的问题
  STMFLASH_Read(FLASH_SAVE_ADDR, (uint16_t*)&Config_Get()->mr16, sizeof(MR16_Param_t)/2);
//  mr16->param->mode=mr16Mode;
//  MR16_FSM=MR16_FSM_INIT;
  SX1281_Init(&radio, &param->radioParams, radioMode);
//    SX1281_SetTX(&radio,uart_data,data_length);
  SX1281_SetRXSuccessive(&radio);
	// LCD显示
  LCD_Init(1);
  LCD_Clear(BLACK);
  LCD_DrawString(0,0,"SX1281",MEDIUMORCHID,32,LSB);
  LCD_DrawBitmap(logo_M,180,80,64,64,CRIMSON,MSB);
}

bool UART2_IdleFlag = false;
void MR16_NotifyUARTIdle(void)
{
  UART2_IdleFlag=true;
}

static char cInputBuffer[64];
static char cOutputBuffer[256];
int8_t MR16_Main(MR16_t *mr16, uint8_t data[],uint8_t data_length) {

  if (UART2_IdleFlag==true) {
    UART2_IdleFlag = false;

    if (uart2_datalength > 0 && uart2_datalength < sizeof(cInputBuffer)) {
      memcpy(cInputBuffer, uart2_data, uart2_datalength);
      cInputBuffer[uart2_datalength] = '\0';
    } else {
      cInputBuffer[0] = '\0';
    }

    cOutputBuffer[0] = '\0';
    BaseType_t xMore = pdTRUE;
    do {
        xMore = FreeRTOS_CLIProcessCommand(cInputBuffer, cOutputBuffer, sizeof(cOutputBuffer));
        if (cOutputBuffer[0] != '\0') {
        printf("%s", cOutputBuffer); 
        }
        cOutputBuffer[0] = '\0';
    } while (xMore == pdTRUE);
  }

  switch (mr16->param->mode) {
    case MR16_MODE_RFUART:

      break;
    case MR16_MODE_RC:
      switch (radio.appMode) {
        case APPMODE_TX:
		      SX1281_Running(&radio);
          SX1281_SetTX(&radio,mr16->txbuffer,mr16->txbuffer[2]+5);
          break;
        case APPMODE_RXSUCCESSIVE:
          SX1281_Running(&radio);
          break;
        default:
          break;
      }
    case MR16_MODE_SETTING:
      break;
    case MR16_MODE_NONE:
      break;
    default:
      break;
  }
}


/*-------------------------------------------------

					  CLI

--------------------------------------------------*/
static const char radio_help_en[] =
"============================================================================\r\n"
"radio <subcmd> [args]  - SX1281 radio control\r\n"
"  mode <BLE|LORA|GFSK|FLRC>        - Change working mode\r\n"
"  modulation <field> <value>       - Set modulation parameters\r\n"
"  packet <field> <value>           - Set packet parameters\r\n"
"  baudrate <mode> <index>          - Set baudrate\r\n"
"  power <dBm>                      - Set TX power (-18..+13)\r\n"
"  ramptime <us>                    - Set ramp time (2|4|6|8|10|12|16|20)\r\n"
"  rffreq <Hz>                      - Set RF frequency\r\n"
"  tx | rx                          - TX/RX operations\r\n"
"  modulation help | packet help    - Show detailed help\r\n"
"============================================================================\r\n";

static const char modulation_help[] =
"============================================================================================================\r\n"
"modulation <field> <value>  - Set modulation parameters\r\n"
"  BLE/GFSK fields:\r\n"
"    br_bw    : 0x04(2.0M/2.4M)||0x28(1.6M/2.4M)||0x4C(1.0M/2.4M)||0x45(1.0M/1.2M)\r\n"
"               0x70(0.8M/2.4M)||0x69(0.8M/1.2M)||0x8D(0.5M/1.2M)||0x86(0.5M/0.6M)\r\n"
"               0xB1(0.4M/1.2M)||0xAA(0.4M/0.6M)||0xCE(0.25M/0.6M)||0xC7(0.25M/0.3M)||0xEF(0.125M/0.3M)\r\n"
"    modindex : 0(0.35)||1(0.50)||2(0.75)||3(1.00)||4(1.25)||5(1.50)||6(1.75)||7(2.00)\r\n"
"               8(2.25)||9(2.50)||10(2.75)||11(3.00)||12(3.25)||13(3.50)||14(3.75)||15(4.00)\r\n"
"    shaping  : 0x00(OFF)||0x10(BT_1_0)||0x20(BT_0_5)\r\n"
"  LORA fields:\r\n"
"    sf : 0x50(SF5)||0x60(SF6)||0x70(SF7)||0x80(SF8)||0x90(SF9)||0xA0(SF10)||0xB0(SF11)||0xC0(SF12)\r\n"
"    bw : 0x34(BW_200K)||0x26(BW_400K)||0x18(BW_800K)||0x0A(BW_1600K)\r\n"
"    cr : 0x01(4/5)||0x02(4/6)||0x03(4/7)||0x04(4/8)||0x05(LI_4/5)||0x06(LI_4/6)||0x07(LI_4/7)\r\n"
"  FLRC fields:\r\n"
"    br_bw    : 0x04(2.6M/2.4M)||0x28(2.08M/2.4M)||0x45(1.3M/1.2M)||0x69(1.04M/1.2M)\r\n"
"               0x86(0.65M/0.6M)||0xAA(0.52M/0.6M)||0xC7(0.325M/0.3M)||0xEB(0.26M/0.3M)\r\n"
"    cr       : 0x00(CR_1/2)||0x02(CR_3/4)||0x04(CR_1/0)\r\n"
"    shaping  : 0x00(OFF)||0x10(BT_1_0)||0x20(BT_0_5)\r\n"
"Examples: radio modulation br_bw 0x4C\r\n"
"          radio modulation sf 0x70\r\n"
"============================================================================================================\r\n";
static const char packet_help[] =
"================================================================================================\r\n"
"packet <field> <value>  - Set packet parameters (current PacketType based)\r\n"
"  BLE fields:\r\n"
"    ConnectionState : 0(MASTER_SLAVE)||1(ADVERTISER)||2(TX_TEST)||3(RX_TEST)||4(RXTX_TEST)\r\n"
"    CrcField        : 0(OFF)||1(CRC_3B)\r\n"
"    BlePacketType   : 0(PRBS_9)||1(PRBS_15)||2(EYELONG_1_0)||3(EYELONG_0_1)\r\n"
"                      4(EYESHORT_1_0)||5(EYESHORT_0_1)||6(ALL_1)||7(ALL_0)\r\n"
"    Whitening       : 0x00(ON)||0x08(OFF)\r\n"
"  GFSK fields:\r\n"
"    Preamble        : 0x00(4bits)||0x10(8bits)||0x20(12bits)||0x30(16bits)\r\n"
"                      0x40(20bits)||0x50(24bits)||0x60(28bits)||0x70(32bits)\r\n"
"    SyncWordLength  : 0x00(1byte)||0x02(2bytes)||0x04(3bytes)||0x06(4bytes)||0x08(5bytes)\r\n"
"    SyncWordMatch   : 0x00(OFF)||0x10(1)||0x20(2)||0x30(1_2)||0x40(3)||0x50(1_3)||0x60(2_3)||0x70(1_2_3)\r\n"
"    Header          : 0x00(VARIABLE)||0x20(FIXED)\r\n"
"    Payload         : 1-255 (bytes)\r\n"
"    Crc             : 0x00(OFF)||0x10(1byte)||0x20(2bytes)||0x30(3bytes)\r\n"
"    Whitening       : 0x00(ON)||0x08(OFF)\r\n"
"  LORA fields:\r\n"
"    Preamble        : 0-255 (symbols count)\r\n"
"    Header          : 0x00(VARIABLE/EXPLICIT)||0x80(FIXED/IMPLICIT)\r\n"
"    Payload         : 1-255 (bytes)\r\n"
"    Crc             : 0x20(ON)||0x00(OFF)\r\n"
"    InvertIQ        : 0x40(NORMAL)||0x00(INVERTED)\r\n"
"  FLRC fields: Same as GFSK (Preamble/SyncWordLength/SyncWordMatch/Header/Payload/Crc/Whitening)\r\n"
"Examples: radio packet Payload 64\r\n"
"          radio packet Crc 0x20\r\n"
"          radio packet Header 0x00\r\n"
"================================================================================================\r\n";

static const char baudrate_help[] =
"=====================================================================\r\n"
"baudrate <mode> <index>  - Set baudrate\r\n"
"  BLE  : 0(250K)||1(500K)||2(1M)\r\n"
"  LORA : 0(216b)||1(1K)||2(5K)||3(10K)||4(20K)||5(61K)||6(127K)||7(203K)\r\n"
"  GFSK : 0(125K)||1(250K)||2(500K)||3(1M)\r\n"
"  FLRC : 0(130K)||1(260K)||2(520K)||3(1040K)\r\n"
"Examples: radio baudrate GFSK 2\r\n"
"          radio baudrate LORA 3\r\n"
"=====================================================================\r\n";
static BaseType_t mr16CommandHandler( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) {
  BaseType_t len1 = 0, len2 = 0;
  const char *p1 = FreeRTOS_CLIGetParameter(pcCommandString, 1, &len1); // 第1个参数（不包含命令名）
  const char *p2 = FreeRTOS_CLIGetParameter(pcCommandString, 2, &len2); // 第2个参数

  char arg1[32] = {0};
  char arg2[32] = {0};

  if (p1) {
    size_t c1 = (len1 < (BaseType_t)(sizeof(arg1)-1)) ? (size_t)len1 : sizeof(arg1)-1;
    strncpy(arg1, p1, c1);
    arg1[c1] = '\0';
  }
  if (p2) {
    size_t c2 = (len2 < (BaseType_t)(sizeof(arg2)-1)) ? (size_t)len2 : sizeof(arg2)-1;
    strncpy(arg2, p2, c2);
    arg2[c2] = '\0';
  }

  if (strcasecmp(arg1, "save") == 0) {
    // 保存配置到Flash
//	  Flash_PageErase(FLASH_SAVE_ADDR);
   STMFLASH_Write(FLASH_SAVE_ADDR, (uint16_t*)&Config_Get()->mr16, sizeof(MR16_Param_t)/2);
//	   STMFLASH_Write(FLASH_SAVE_ADDR, (uint16_t*)&Config_Get()->mr16.TX_ID, 1);
    // BSP_Flash_EraseSector(200);
    // BSP_Flash_WriteBytes(ADDR_FLASH_SECTOR(200), (const uint8_t*)&Config_Get()->mr16, sizeof(MR16_Param_t));
    snprintf(pcWriteBuffer, xWriteBufferLen, "Configuration saved to Flash!\r\n");
  } else if(strcasecmp(arg1, "get") == 0){
    // 从Flash读取配置，测试使用
    STMFLASH_Read(FLASH_SAVE_ADDR, (uint16_t*)&Config_Get()->mr16, sizeof(MR16_Param_t)/2);
    snprintf(pcWriteBuffer, xWriteBufferLen, "%s\r\n", (char *)&Config_Get()->mr16);
  } else if (strcasecmp(arg1, "mode") == 0) {
    if (arg2[0] != '\0') {
      if (strcasecmp(arg2, "RFUART") == 0) {
        mr16.param->mode = MR16_MODE_RFUART;
        snprintf(pcWriteBuffer, xWriteBufferLen, "mode set to: %s\r\n", arg2);
      } else if (strcasecmp(arg2, "RC") == 0) {
        mr16.param->mode = MR16_MODE_RC;
        snprintf(pcWriteBuffer, xWriteBufferLen, "mode set to: %s\r\n", arg2);
      } else {
        snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid mode: %s\r\n", arg2);
        return pdFALSE;
      }
    }
    snprintf(pcWriteBuffer, xWriteBufferLen, "Set -> %s\r\n", arg2);
  } else if (strcasecmp(arg1, "tx") == 0){
	  SX1281_SetTX(&radio,mr16.txbuffer,mr16.txbuffer[2]+5);
  }	else if (strcasecmp(arg1, "rx") == 0){
	  SX1281_SetRXSuccessive(&radio);
  } else if (strcasecmp(arg1, "rxid1") == 0) {
    if (arg2[0] != '\0') {
      uint16_t rxid;
      sscanf(arg2, "%hx", &rxid);
      if(rxid >0x0001 && rxid <0xFFFE){
        mr16.param->RX_ID[0] = rxid;
        snprintf(pcWriteBuffer, xWriteBufferLen, "RXID1 set to: 0x%04X\r\n", mr16.param->RX_ID[0]);
      }else{
        snprintf(pcWriteBuffer, xWriteBufferLen, "RXID1 set failed: invalid value\r\n");
        snprintf(pcWriteBuffer, xWriteBufferLen, "RXID1 now: 0x%04X\r\n", mr16.param->RX_ID[0]);
      }
    }
  }

  return pdFALSE;
}

static BaseType_t radioCommandHandler( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) {
  BaseType_t len1 = 0, len2 = 0, len3 = 0, len4 = 0;
  const char *p1 = FreeRTOS_CLIGetParameter(pcCommandString, 1, &len1); // 第1个参数（不包含命令名）
  const char *p2 = FreeRTOS_CLIGetParameter(pcCommandString, 2, &len2); // 第2个参数
  const char *p3 = FreeRTOS_CLIGetParameter(pcCommandString, 3, &len3); // 第3个参数
  const char *p4 = FreeRTOS_CLIGetParameter(pcCommandString, 4, &len4); // 第4个参数

  char arg1[32] = {0};
  char arg2[32] = {0};
  char arg3[32] = {0};
  char arg4[32] = {0};

  if (p1) { size_t c1 = (len1 < (BaseType_t)(sizeof(arg1)-1)) ? (size_t)len1 : sizeof(arg1)-1; strncpy(arg1, p1, c1); arg1[c1] = '\0'; }
  if (p2) { size_t c2 = (len2 < (BaseType_t)(sizeof(arg2)-1)) ? (size_t)len2 : sizeof(arg2)-1; strncpy(arg2, p2, c2); arg2[c2] = '\0'; }
  if (p3) { size_t c3 = (len3 < (BaseType_t)(sizeof(arg3)-1)) ? (size_t)len3 : sizeof(arg3)-1; strncpy(arg3, p3, c3); arg3[c3] = '\0'; }
  if (p4) { size_t c4 = (len4 < (BaseType_t)(sizeof(arg4)-1)) ? (size_t)len4 : sizeof(arg4)-1; strncpy(arg4, p4, c4); arg4[c4] = '\0'; }

  /*
  help命令
  */
    if (strcasecmp(arg1, "help") == 0) {
    static size_t help_pos = 0;
    size_t help_len = strlen(radio_help_en);
    if (help_pos >= help_len) {
      help_pos = 0;
      return pdFALSE;
    }
    size_t chunk = (xWriteBufferLen > 1) ? (xWriteBufferLen - 1) : 0;
    size_t remain = help_len - help_pos;
    size_t to_copy = (remain < chunk) ? remain : chunk;
    if (to_copy > 0) {
      memcpy(pcWriteBuffer, radio_help_en + help_pos, to_copy);
      pcWriteBuffer[to_copy] = '\0';
      help_pos += to_copy;
      return (help_pos < help_len) ? pdTRUE : pdFALSE;
    }
    help_pos = 0;
    return pdFALSE;
  } else if (strcasecmp(arg1, "modulation") == 0 && strcasecmp(arg2, "help") == 0) {
    static size_t mod_help_pos = 0;
    size_t mod_help_len = strlen(modulation_help);
    if (mod_help_pos >= mod_help_len) {
      mod_help_pos = 0;
      return pdFALSE;
    }
    size_t chunk = (xWriteBufferLen > 1) ? (xWriteBufferLen - 1) : 0;
    size_t remain = mod_help_len - mod_help_pos;
    size_t to_copy = (remain < chunk) ? remain : chunk;
    if (to_copy > 0) {
      memcpy(pcWriteBuffer, modulation_help + mod_help_pos, to_copy);
      pcWriteBuffer[to_copy] = '\0';
      mod_help_pos += to_copy;
      return (mod_help_pos < mod_help_len) ? pdTRUE : pdFALSE;
    }
    mod_help_pos = 0;
    return pdFALSE;
  } else if (strcasecmp(arg1, "packet") == 0 && strcasecmp(arg2, "help") == 0) {
    static size_t pkt_help_pos = 0;
    size_t pkt_help_len = strlen(packet_help);
    if (pkt_help_pos >= pkt_help_len) {
      pkt_help_pos = 0;
      return pdFALSE;
    }
    size_t chunk = (xWriteBufferLen > 1) ? (xWriteBufferLen - 1) : 0;
    size_t remain = pkt_help_len - pkt_help_pos;
    size_t to_copy = (remain < chunk) ? remain : chunk;
    if (to_copy > 0) {
      memcpy(pcWriteBuffer, packet_help + pkt_help_pos, to_copy);
      pcWriteBuffer[to_copy] = '\0';
      pkt_help_pos += to_copy;
      return (pkt_help_pos < pkt_help_len) ? pdTRUE : pdFALSE;
    }
    pkt_help_pos = 0;
    return pdFALSE;
  } else if (strcasecmp(arg1, "baudrate") == 0 && strcasecmp(arg2, "help") == 0) {
    snprintf(pcWriteBuffer, xWriteBufferLen, "%s", baudrate_help);
    return pdFALSE;
  }


  /* 
  修改参数命令
  */
  unsigned long val = 0;
  if (arg4[0] != '\0') val = strtoul(arg4, NULL, 0);
  else if (arg3[0] != '\0') val = strtoul(arg3, NULL, 0);

  /* Process commands */
  if (strcasecmp(arg1, "mode") == 0) {
    /* radio mode change: arg2 = BLE/LORA/GFSK/FLRC */
    SX1281_RadioMode_t proto;
    if (strcasecmp(arg2, "BLE") == 0) proto = RADIOMODE_BLE;
    else if (strcasecmp(arg2, "LORA") == 0) proto = RADIOMODE_LORA;
    else if (strcasecmp(arg2, "GFSK") == 0) proto = RADIOMODE_GFSK;
    else if (strcasecmp(arg2, "FLRC") == 0) proto = RADIOMODE_FLRC;
    else {
      snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown radio mode: %s\r\n", arg2);
      return pdFALSE;
    }
    if (SX1281_SetMode(&radio, proto) == DEVICE_OK) {
      snprintf(pcWriteBuffer, xWriteBufferLen, "Radio mode set to %s\r\n", arg2);
    } else {
      snprintf(pcWriteBuffer, xWriteBufferLen, "Failed to set radio mode\r\n");
      return pdFALSE;
    }
  } else if (strcasecmp(arg1, "modulation") == 0) {

    switch (radio.param->modulationParams.PacketType) {
      case PACKET_TYPE_BLE:
          if (strcasecmp(arg2, "br_bw") == 0) {
            if (val > 0xEF) { snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid br_bw value for BLE\r\n"); return pdFALSE; }
            radio.param->modulationParams.Params.Ble.BitrateBandwidth = (RadioGfskBleBitrates_t)val;
          }
          else if (strcasecmp(arg2, "modindex") == 0) {
            if (val > 15) { snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid modindex value for BLE\r\n"); return pdFALSE; }
            radio.param->modulationParams.Params.Ble.ModulationIndex = (RadioGfskBleModIndexes_t)val;
          }
          else if (strcasecmp(arg2, "shaping") == 0) {
            if (val != 0x00 && val != 0x10 && val != 0x20) { snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid shaping value for BLE\r\n"); return pdFALSE; }
            radio.param->modulationParams.Params.Ble.ModulationShaping = (RadioModShapings_t)val;
          }
          else { snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown modulation field\r\n"); return pdFALSE; }
        break;
      case PACKET_TYPE_GFSK:
          if (strcasecmp(arg2, "br_bw") == 0) {
            if (val > 0xEF) { snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid br_bw value for GFSK\r\n"); return pdFALSE; }
            radio.param->modulationParams.Params.Gfsk.BitrateBandwidth = (RadioGfskBleBitrates_t)val;
          }
          else if (strcasecmp(arg2, "modindex") == 0) {
            if (val > 15) { snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid modindex value for GFSK\r\n"); return pdFALSE; }
            radio.param->modulationParams.Params.Gfsk.ModulationIndex = (RadioGfskBleModIndexes_t)val;
          }
          else if (strcasecmp(arg2, "shaping") == 0) {
            if (val != 0x00 && val != 0x10 && val != 0x20) { snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid shaping value for GFSK\r\n"); return pdFALSE; }
            radio.param->modulationParams.Params.Gfsk.ModulationShaping = (RadioModShapings_t)val;
          }
          else { snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown modulation field\r\n"); return pdFALSE; }
        break;
      case PACKET_TYPE_LORA:
          if (strcasecmp(arg2, "sf") == 0) {
            if (val != 0x50 && val != 0x60 && val != 0x70 && val != 0x80 && val != 0x90 && val != 0xA0 && val != 0xB0 && val != 0xC0) {
              snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid sf value for LORA\r\n"); return pdFALSE;
            }
            radio.param->modulationParams.Params.LoRa.SpreadingFactor = (RadioLoRaSpreadingFactors_t)val;
          }
          else if (strcasecmp(arg2, "bw") == 0) {
            if (val != 0x34 && val != 0x26 && val != 0x18 && val != 0x0A) { snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid bw value for LORA\r\n"); return pdFALSE; }
            radio.param->modulationParams.Params.LoRa.Bandwidth = (RadioLoRaBandwidths_t)val;
          }
          else if (strcasecmp(arg2, "cr") == 0) {
            if (val < 0x01 || val > 0x07) { snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid cr value for LORA\r\n"); return pdFALSE; }
            radio.param->modulationParams.Params.LoRa.CodingRate = (RadioLoRaCodingRates_t)val;
          }
          else { snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown modulation field\r\n"); return pdFALSE; }
        break;
      case PACKET_TYPE_FLRC:
          if (strcasecmp(arg2, "br_bw") == 0) {
            if (val != 0x04 && val != 0x28 && val != 0x45 && val != 0x69 && val != 0x86 && val != 0xAA && val != 0xC7 && val != 0xEB) {
              snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid br_bw value for FLRC\r\n"); return pdFALSE;
            }
            radio.param->modulationParams.Params.Flrc.BitrateBandwidth = (RadioFlrcBitrates_t)val;
          }
          else if (strcasecmp(arg2, "cr") == 0) {
            if (val != 0x00 && val != 0x02 && val != 0x04) { snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid cr value for FLRC\r\n"); return pdFALSE; }
            radio.param->modulationParams.Params.Flrc.CodingRate = (RadioFlrcCodingRates_t)val;
          }
          else if (strcasecmp(arg2, "shaping") == 0) {
            if (val != 0x00 && val != 0x10 && val != 0x20) { snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid shaping value for FLRC\r\n"); return pdFALSE; }
            radio.param->modulationParams.Params.Flrc.ModulationShaping = (RadioModShapings_t)val;
          }
          else { snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown modulation field\r\n"); return pdFALSE; }
        break;
      default:
        snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown current packet type\r\n");
        return pdFALSE;
    }
    Radio.SetModulationParams(&radio.param->modulationParams);
    snprintf(pcWriteBuffer, xWriteBufferLen, "Modulation updated\r\n");
  } else if (strcasecmp(arg1, "packet") == 0) {
    /* packet <proto> <field> <value>
       fields examples: payload | preamble | header | crc | whitening
    */
    /* 根据当前 packet type 设置对应字段 */
    switch (radio.param->packetParams.PacketType) {

      case PACKET_TYPE_BLE:
        /* BLE 使用 Ble 子结构 */
        if (strcasecmp(arg2, "ConnectionState") == 0) {
          radio.param->packetParams.Params.Ble.ConnectionState = (RadioBleConnectionStates_t)val;
        } else if (strcasecmp(arg2, "CrcField") == 0) {
          radio.param->packetParams.Params.Ble.CrcField = (RadioBleCrcFields_t)val;
        } else if (strcasecmp(arg2, "BlePacketType") == 0) {
          radio.param->packetParams.Params.Ble.BlePacketType = (RadioBlePacketTypes_t)val;
        } else if (strcasecmp(arg2, "Whitening") == 0) {
          radio.param->packetParams.Params.Ble.Whitening = (RadioWhiteningModes_t)val;
        } else {
          snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown BLE packet field\r\n");
          return pdFALSE;
        }
        break;

      case PACKET_TYPE_GFSK:
        /* GFSK 子结构 */
        if (strcasecmp(arg2, "Preamble") == 0) {
          radio.param->packetParams.Params.Gfsk.PreambleLength = (RadioPreambleLengths_t)val;
        } else if (strcasecmp(arg2, "SyncWordLength") == 0) {
          radio.param->packetParams.Params.Gfsk.SyncWordLength = (RadioSyncWordLengths_t)val;
        } else if (strcasecmp(arg2, "SyncWordMatch") == 0) {
          radio.param->packetParams.Params.Gfsk.SyncWordMatch = (RadioSyncWordRxMatchs_t)val;
        } else if (strcasecmp(arg2, "Header") == 0) {
          radio.param->packetParams.Params.Gfsk.HeaderType = (RadioPacketLengthModes_t)val;
        } else if (strcasecmp(arg2, "Payload") == 0) {
          radio.param->packetParams.Params.Gfsk.PayloadLength = (uint8_t)val;
        } else if (strcasecmp(arg2, "Crc") == 0) {
          radio.param->packetParams.Params.Gfsk.CrcLength = (RadioCrcTypes_t)val;
        } else if (strcasecmp(arg2, "Whitening") == 0) {
          radio.param->packetParams.Params.Gfsk.Whitening = (RadioWhiteningModes_t)val;
        } else {
          snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown GFSK packet field\r\n");
          return pdFALSE;
        }
        break;

      case PACKET_TYPE_LORA:
        /* LoRa 子结构 */
        if (strcasecmp(arg2, "Preamble") == 0) {
          radio.param->packetParams.Params.LoRa.PreambleLength = (uint8_t)val;
        } else if (strcasecmp(arg2, "Header") == 0) {
          radio.param->packetParams.Params.LoRa.HeaderType = (RadioLoRaPacketLengthsModes_t)val;
        } else if (strcasecmp(arg2, "Payload") == 0) {
          radio.param->packetParams.Params.LoRa.PayloadLength = (uint8_t)val;
        } else if (strcasecmp(arg2, "Crc") == 0) {
          radio.param->packetParams.Params.LoRa.CrcMode = (RadioLoRaCrcModes_t)val;
        } else if (strcasecmp(arg2, "InvertIQ") == 0) {
          radio.param->packetParams.Params.LoRa.InvertIQ = (RadioLoRaIQModes_t)val;
        } else {
          snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown LoRa packet field\r\n");
          return pdFALSE;
        }
        break;

      case PACKET_TYPE_FLRC:
        /* FLRC 子结构 */
        if (strcasecmp(arg2, "Preamble") == 0) {
          radio.param->packetParams.Params.Flrc.PreambleLength = (RadioPreambleLengths_t)val;
        } else if (strcasecmp(arg2, "SyncWordLength") == 0) {
          radio.param->packetParams.Params.Flrc.SyncWordLength = (RadioFlrcSyncWordLengths_t)val;
        } else if (strcasecmp(arg2, "SyncWordMatch") == 0) {
          radio.param->packetParams.Params.Flrc.SyncWordMatch = (RadioSyncWordRxMatchs_t)val;
        } else if (strcasecmp(arg2, "Header") == 0) {
          radio.param->packetParams.Params.Flrc.HeaderType = (RadioPacketLengthModes_t)val;
        } else if (strcasecmp(arg2, "Payload") == 0) {
          radio.param->packetParams.Params.Flrc.PayloadLength = (uint8_t)val;
        } else if (strcasecmp(arg2, "Crc") == 0) {
          radio.param->packetParams.Params.Flrc.CrcLength = (RadioCrcTypes_t)val;
        } else if (strcasecmp(arg2, "Whitening") == 0) {
          radio.param->packetParams.Params.Flrc.Whitening = (RadioWhiteningModes_t)val;
        } else {
          snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown FLRC packet field\r\n");
          return pdFALSE;
        }
        break;

      default:
        snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown current packet type\r\n");
        return pdFALSE;
    }

    /* 应用并返回 */
    Radio.SetPacketParams(&radio.param->packetParams);
    snprintf(pcWriteBuffer, xWriteBufferLen, "Packet parameters updated\r\n");
  } else if (strcasecmp(arg1, "baudrate") == 0) {
    /* baudrate <proto> <value> */
    SX1281_RadioMode_t proto;
    int8_t ret = -1;
    if (strcasecmp(arg2, "BLE") == 0) {
      radio.param->baudrate.ble = (SX1281_BLEBaudrate_t)val;
      ret = SX1281_SetBLEBaudrate(&radio, radio.param->baudrate.ble);
    } else if (strcasecmp(arg2, "LORA") == 0) {
      radio.param->baudrate.lora = (SX1281_LORABaudrate_t)val;
      ret = SX1281_SetLORABaudrate(&radio, radio.param->baudrate.lora);
    } else if (strcasecmp(arg2, "GFSK") == 0) {
      radio.param->baudrate.gfks = (SX1281_GFKSBaudrate_t)val;
      ret = SX1281_SetGFSKBaudrate(&radio, radio.param->baudrate.gfks);
    } else if (strcasecmp(arg2, "FLRC") == 0) {
      radio.param->baudrate.flrc = (SX1281_FLRCBaudrate_t)val;
      ret = SX1281_SetFLRCBaudrate(&radio, radio.param->baudrate.flrc);
    } else {
      snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown proto: %s\r\n", arg2);
      return pdFALSE;
    }
    if (ret == DEVICE_OK) {
      snprintf(pcWriteBuffer, xWriteBufferLen, "Baudrate updated for %s -> %lu\r\n", arg2, (unsigned long)val);
    } else {
      snprintf(pcWriteBuffer, xWriteBufferLen, "Failed to update baudrate for %s\r\n", arg2);
    }
  } else if (strcasecmp(arg1, "power") == 0) {
    /* power <value> */
    int8_t p = (int8_t)val;
    radio.param->txOutputPower = p;
    Radio.SetTxParams(radio.param->txOutputPower, radio.param->rampTime);
    snprintf(pcWriteBuffer, xWriteBufferLen, "TX power set to %d dBm\r\n", p);
  } else if (strcasecmp(arg1, "ramptime") == 0) {
    /* ramptime <us> - accepts 2/4/6/8/10/12/16/20 */
    RadioRampTimes_t rt = RADIO_RAMP_02_US;
    unsigned long us = val;
    switch (us) {
      case 2: rt = RADIO_RAMP_02_US; break;
      case 4: rt = RADIO_RAMP_04_US; break;
      case 6: rt = RADIO_RAMP_06_US; break;
      case 8: rt = RADIO_RAMP_08_US; break;
      case 10: rt = RADIO_RAMP_10_US; break;
      case 12: rt = RADIO_RAMP_12_US; break;
      case 16: rt = RADIO_RAMP_16_US; break;
      case 20: rt = RADIO_RAMP_20_US; break;
      default: snprintf(pcWriteBuffer, xWriteBufferLen, "Invalid ramptime\r\n"); return pdFALSE;
    }
    radio.param->rampTime = rt;
    Radio.SetTxParams(radio.param->txOutputPower, radio.param->rampTime);
    snprintf(pcWriteBuffer, xWriteBufferLen, "Ramp time set to %lu us\r\n", us);
  } else if (strcasecmp(arg1, "rffreq") == 0 || strcasecmp(arg1, "rffrequency") == 0) {
    /* rffreq <value in Hz> */
    uint32_t f = (uint32_t)val;
    SX1281_SetRFFrequency(&radio, f);
    snprintf(pcWriteBuffer, xWriteBufferLen, "RF freq set to %lu Hz\r\n", (unsigned long)f);
  } else {
    snprintf(pcWriteBuffer, xWriteBufferLen, "Unknown radio command\r\n");
  }

  return pdFALSE;
}




int8_t MR16_CLI_Init() {
    static const CLI_Command_Definition_t mr16Command = {
        "mr16", // 命令名
        "mr16 <save|mode|TX|RX|rxid1|rxid2|rxid3>\r\n", // 帮助信息
        mr16CommandHandler, // 处理函数
        -1 // 可变参数数量
    };
    static const CLI_Command_Definition_t radioCommand = {
    "radio", // 命令名
    "radio - radio subcommands. Use 'radio help' for detailed usage.\r\n", // 帮助信息（详尽）
    radioCommandHandler, // 处理函数
    -1 // 可变参数数量
    };
    FreeRTOS_CLIRegisterCommand(&mr16Command);
    FreeRTOS_CLIRegisterCommand(&radioCommand);
}