/* Includes ----------------------------------------------------------------- */ #include "module/mr16.h" #include #include #include #include #include #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, ¶m->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 [args] - SX1281 radio control\r\n" " mode - Change working mode\r\n" " modulation - Set modulation parameters\r\n" " packet - Set packet parameters\r\n" " baudrate - Set baudrate\r\n" " power - Set TX power (-18..+13)\r\n" " ramptime - Set ramp time (2|4|6|8|10|12|16|20)\r\n" " rffreq - 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 - 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 - 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 - 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 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 */ 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 */ 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 - 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 */ 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 \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); }