737 lines
31 KiB
C
737 lines
31 KiB
C
/* 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, ¶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 <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);
|
||
} |