MR16/User/module/mr16.c
2025-12-04 21:52:36 +08:00

737 lines
31 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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);
}