-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
34 changed files
with
3,979 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
/* | ||
This file is part of the CLI module. | ||
It contains the functionallity to handle the CLI commands. | ||
You should NOT ADD COMMANDS HERE. Use cli_cmd_callbacks.c instead. | ||
*/ | ||
|
||
#include "cli.h" | ||
|
||
#include <stdint.h> | ||
|
||
#include "usbd_cdc_if.h" | ||
|
||
#include "log.h" | ||
#include "version.h" | ||
#include "misc.h" | ||
#include "cli_cmd_callbacks.h" | ||
#include "main.h" | ||
|
||
void cli_handle_cmd(cli_handle_t *cli_h); | ||
|
||
void cli_process(void *arg) { | ||
if (arg == NULL) { | ||
LOGE("cli_process: arg is NULL! Not processing cli... unsafe!"); | ||
return; | ||
} | ||
cli_handle_t *cli_h = (cli_handle_t *)arg; | ||
|
||
// read data | ||
if (cli_h->new_data_flag) { // if new data data in buffer | ||
cli_h->new_data_flag = false; | ||
LOG("-> %s", cli_h->cli_rx_buffer); | ||
cli_handle_cmd(cli_h); | ||
} | ||
|
||
//write data (from buffer) | ||
} | ||
|
||
void cli_init(cli_handle_t *cli_h) { | ||
LOGD("CLI Init..."); | ||
|
||
cli_h->cli_connected_flag = false; | ||
|
||
uint8_t version_string[10]; | ||
VERSION_TO_STRING(CLI_VERSION, version_string); | ||
LOGD("CLI is on version %s", version_string); | ||
|
||
//init the cmd_list array to NULL | ||
for (size_t i = 0; i < MAX_CMD_COUNT; i++) { | ||
cli_h->cmd_list[i].cmd_str = NULL; | ||
} | ||
|
||
cli_h->new_data_flag = false; | ||
|
||
add_commands(cli_h); | ||
|
||
//wait for connection | ||
if (cli_h->cli_connected_flag == false && cli_h->halt_until_connected_flag == true) { | ||
LOGD("Waiting for connection..."); | ||
while (cli_h->cli_connected_flag == false) { | ||
LED_toggle(); | ||
delay(100); | ||
if (cli_h->new_data_flag == true) { | ||
cli_h->new_data_flag = false; | ||
|
||
// check for "connect" cmd | ||
if (strcmp_ign(cli_h->cli_rx_buffer, (uint8_t *)"connect") == 0) { | ||
cli_h->cli_connected_flag = true; | ||
LOGD("Connection confirmed"); | ||
} | ||
//check for "dfu" cmd | ||
if (strcmp_ign(cli_h->cli_rx_buffer, (uint8_t *)"dfu") == 0) { | ||
reboot_into_dfu(); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
void cli_handle_cmd(cli_handle_t *cli_h) { | ||
// find the command index | ||
uint8_t *raw_cmd_str = cli_h->cli_rx_buffer; | ||
|
||
// take first word as command | ||
uint8_t *cmd_str = (uint8_t *)strtok((char *)raw_cmd_str, " "); | ||
|
||
//clean arg array | ||
for (int i = 0; i < MAX_ARGS_COUNT; i++) { | ||
cli_h->last_args[i] = (uint8_t*)""; | ||
} | ||
|
||
// array to hold the arguments | ||
uint8_t arg_count = 0; | ||
|
||
// get the rest of the arguments | ||
while (arg_count < MAX_ARGS_COUNT) { | ||
cli_h->last_args[arg_count] = (uint8_t *)strtok(NULL, " "); | ||
if (cli_h->last_args[arg_count] == NULL) { | ||
break; | ||
} | ||
clean_str(cli_h->last_args[arg_count]); // removes any \n or \r | ||
arg_count++; | ||
} | ||
cli_h->last_args_count = arg_count; //save last count so cmd callbacks know how many args there are | ||
|
||
int8_t cmd_index = -1; | ||
|
||
for (int8_t i = 0; i < MAX_CMD_COUNT; i++) { | ||
if (cli_h->cmd_list[i].cmd_str != NULL) { | ||
if (strcmp_ign(cli_h->cmd_list[i].cmd_str, cmd_str) == 0) { | ||
cmd_index = i; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if (cmd_index == -1) { | ||
LOGE("The command you entered does not exist: %s, try again", cmd_str); | ||
return; | ||
} | ||
|
||
if (cli_h->cmd_list[cmd_index].cmd_callback != NULL) { | ||
cli_h->cmd_list[cmd_index].cmd_callback(cli_h); | ||
} else { | ||
LOGE("The command you entered has no callback, it is most likely not implemented yet: %s", cmd_str); | ||
} | ||
} | ||
|
||
|
||
void cli_add_cmd(cli_handle_t *cli_h, uint8_t *cmd_str, callback_t cmd_callback) { | ||
//check if cmd_str is already an existing command | ||
for (size_t i = 0; i < MAX_CMD_COUNT; i++) { | ||
if (strcmp_ign(cmd_str, (uint8_t *)cli_h->cmd_list[i].cmd_str) == 0) { | ||
LOGE((uint8_t *)"Command already exists, not adding... %s", cmd_str); | ||
return; | ||
} | ||
} | ||
|
||
//find an empty slot in the command list | ||
for (size_t i = 0; i < MAX_CMD_COUNT; i++) { | ||
if (cli_h->cmd_list[i].cmd_str == NULL) { | ||
cli_h->cmd_list[i].cmd_str = cmd_str; | ||
cli_h->cmd_list[i].cmd_callback = cmd_callback; | ||
|
||
if (cmd_callback == NULL) { | ||
LOGW((uint8_t *)"Command added without callback: %s", cmd_str); | ||
return; | ||
} | ||
|
||
LOGD((uint8_t *)"Command added: %s", cmd_str); | ||
return; | ||
} | ||
} | ||
|
||
LOGE((uint8_t *)"No empty slot found for command %s, Increase MAX_CMD_COUNT", cmd_str); | ||
} | ||
|
||
// cli_rx_callback gets called when cli_rx_buffer gets updated with new data | ||
void cli_rx_callback(cli_handle_t* cli_h) { | ||
cli_h->new_data_flag = true; | ||
// don't copy data here... will break receive function. | ||
//TODO: Add a true callback... | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// | ||
// Created by Isaak on 2/21/2024. | ||
// | ||
|
||
#ifndef BETTERFLIGHT_CLI_H | ||
#define BETTERFLIGHT_CLI_H | ||
|
||
#include "version.h" | ||
#include "misc.h" | ||
|
||
#define MAX_CMD_COUNT 64 | ||
#define MAX_ARGS_COUNT 16 | ||
|
||
typedef struct { | ||
uint8_t *cmd_str; | ||
callback_t cmd_callback; | ||
}cli_cmd_t; | ||
|
||
typedef struct { | ||
cli_cmd_t cmd_list[MAX_CMD_COUNT]; | ||
version_t version; | ||
uint8_t cli_rx_buffer[64]; | ||
uint8_t cli_tx_buffer[64]; | ||
bool new_data_flag; | ||
bool cli_connected_flag; | ||
bool halt_until_connected_flag; | ||
uint8_t last_cmd_index; | ||
uint8_t *last_args[MAX_ARGS_COUNT]; | ||
uint8_t last_args_count; | ||
} cli_handle_t; | ||
|
||
void cli_init(cli_handle_t *cli_h); | ||
void cli_process(void *arg); | ||
|
||
void cli_rx_callback(cli_handle_t* cli_h); | ||
void cli_add_cmd(cli_handle_t* cli_h, uint8_t *cmd_str, callback_t cmd_callback); | ||
|
||
|
||
#endif //BETTERFLIGHT_CLI_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
/* | ||
This file is part of the CLI module. | ||
It contains the callback functions that are called when a command is received. | ||
You have to be here and NOT IN CLI.C to add new commands | ||
To add a command: | ||
1. Add a new callback function | ||
2. Add the callback function and cli command string to the add_commands function (below cb's) | ||
*/ | ||
|
||
#include "cli_cmd_callbacks.h" | ||
|
||
#include <stdint.h> | ||
#include <stdio.h> | ||
|
||
#include "cli.h" | ||
#include "log.h" | ||
#include "version.h" | ||
#include "misc.h" | ||
#include "main.h" | ||
#include "mymain.h" | ||
#include "motors.h" | ||
|
||
|
||
void cli_cb_status(cli_handle_t *cli_h) { | ||
LOGI("Status: OK"); | ||
} | ||
|
||
void cli_cb_help(cli_handle_t *cli_h) { | ||
LOG("[RSP] Available commands:"); | ||
for (uint8_t i = 0; i < MAX_CMD_COUNT; i++) { | ||
if (cli_h->cmd_list[i].cmd_str != NULL) { | ||
LOG("%s", cli_h->cmd_list[i].cmd_str); | ||
} | ||
} | ||
} | ||
|
||
void cli_cb_dfu(cli_handle_t *cli_h) { | ||
LOGI("Rebooting into DFU mode..."); | ||
reboot_into_dfu(); | ||
} | ||
|
||
void cli_cb_reboot(cli_handle_t *cli_h) { | ||
LOGI("Rebooting..."); | ||
HAL_Delay(100); //wait for msg to be sent | ||
NVIC_SystemReset(); | ||
} | ||
|
||
void cli_cb_version(cli_handle_t *cli_h) { | ||
uint8_t version_string[10]; | ||
VERSION_TO_STRING(CLI_VERSION, version_string); | ||
LOG("[RSP] %s", version_string); | ||
} | ||
|
||
void cli_cb_connect(cli_handle_t *cli_h) { | ||
LOG((uint8_t *) "[RSP] Confirm Connection"); | ||
cli_h->cli_connected_flag = true; | ||
} | ||
|
||
void cli_cb_disconnect(cli_handle_t *cli_h) { | ||
LOG((uint8_t *) "[RSP] Confirm Disconnection"); | ||
cli_h->cli_connected_flag = false; | ||
} | ||
|
||
void cli_cb_clidemo(cli_handle_t *cli_h) { | ||
LOGD("This is a Debug message"); | ||
LOGI("This is an Info message"); | ||
LOGW("This is a Warning message"); | ||
LOGE("This is an Error message"); | ||
LOG("This is a normal message (should not be used...)"); | ||
LOG("[RSP] This is a response message to a cli command"); | ||
} | ||
|
||
callback_t cli_cb_none(cli_handle_t *cli_h) { | ||
LOGI("Command not implemented yet"); | ||
} | ||
|
||
// --- MOTORS --- // | ||
|
||
void cli_cb_set_motor(cli_handle_t *cli_h) { | ||
LOG("[RSP] Setting motor %s to %s", (char*)cli_h->last_args[0], (char*)cli_h->last_args[1]); | ||
|
||
if (cli_h->last_args_count != 2) { | ||
LOGE("Invalid number of arguments, 2 expected"); | ||
return; | ||
} | ||
|
||
uint8_t motor_nr = char_to_uint16((char*)cli_h->last_args[0]); | ||
if (motor_nr < 1 || motor_nr > 4) { | ||
LOGE("Invalid motor number, 1 to 4 expected"); | ||
return; | ||
} | ||
|
||
uint16_t motor_value = char_to_uint16((char*)cli_h->last_args[1]); | ||
motor_set_throttle(&motors_h, motor_nr, motor_value); | ||
} | ||
|
||
void cli_cb_set_motors(cli_handle_t *cli_h) { | ||
uint16_t motor_values[4]; | ||
if (cli_h->last_args_count == 1) { | ||
for (uint8_t i = 0; i < 4; i++) { | ||
motor_values[i] = (char_to_uint16((char*)cli_h->last_args[0])); | ||
} | ||
} else if (cli_h->last_args_count == 4) { | ||
for (uint8_t i = 0; i < 4; ++i) { | ||
motor_values[i] = (char_to_uint16((char*)cli_h->last_args[i])); | ||
delay(1); | ||
} | ||
} else { | ||
LOGE("Invalid number of arguments, 1 to set all motors to the same value, 4 to set each motor individually!"); | ||
return; | ||
} | ||
|
||
LOG("[RSP] Set Motor valuese to: m1: %d m2: %d m3: %d m4: %d", motor_values[0], motor_values[1], motor_values[2], motor_values[3]); | ||
motors_set_throttle_arr(&motors_h, motor_values); | ||
} | ||
|
||
|
||
void cli_cb_stop_motors(cli_handle_t *cli_h) { | ||
motors_stop(&motors_h); | ||
LOG("[RSP] Motors stopped"); | ||
} | ||
|
||
void cli_cb_beep_motors(cli_handle_t *cli_h) { | ||
motors_beep(&motors_h); | ||
LOG("[RSP] Motors beeped"); | ||
} | ||
|
||
void cli_cb_set_motor_direction(cli_handle_t *cli_h) { | ||
LOG("[RSP] Setting motor (%s) direction to %s", (char*)cli_h->last_args[0], (char*)cli_h->last_args[1]); | ||
|
||
if (cli_h->last_args_count != 2) { | ||
LOGE("Invalid number of arguments, 2 expected"); | ||
return; | ||
} | ||
|
||
uint8_t motor_nr = char_to_uint16((char*)cli_h->last_args[0]); | ||
if (motor_nr < 1 || motor_nr > 4) { | ||
LOGE("Invalid motor number, 1 to 4 expected"); | ||
return; | ||
} | ||
|
||
bool motor_dir = char_to_uint16((char*)cli_h->last_args[1]); | ||
if (motor_dir != 0 && motor_dir != 1) { | ||
LOGE("Invalid motor direction, 0 or 1 expected"); | ||
return; | ||
} | ||
|
||
motor_set_direction(&motors_h, motor_nr, motor_dir); | ||
} | ||
|
||
// --- EOF MOTORS --- // | ||
|
||
void cli_cb_sendsc(cli_handle_t *cli_h) { | ||
LOG("[RSP] Sending motor %d cmd %d" , char_to_uint16((char*)cli_h->last_args[0]), char_to_uint16((char*)cli_h->last_args[1])); | ||
dshot_send_special_command(motors_h.dshot_hs[char_to_uint16((char*)cli_h->last_args[0]) - 1], char_to_uint16((char*)cli_h->last_args[1])); | ||
} | ||
|
||
|
||
void add_commands(cli_handle_t *cli_h) { | ||
cli_add_cmd(cli_h, (uint8_t *)"help", (callback_t) cli_cb_help); | ||
cli_add_cmd(cli_h, (uint8_t *)"status", (callback_t) cli_cb_status); | ||
cli_add_cmd(cli_h, (uint8_t *)"version", (callback_t) cli_cb_version); | ||
cli_add_cmd(cli_h, (uint8_t *)"connect", (callback_t) cli_cb_connect); | ||
cli_add_cmd(cli_h, (uint8_t *)"save", NULL); | ||
cli_add_cmd(cli_h, (uint8_t *)"dfu", (callback_t) cli_cb_dfu); | ||
cli_add_cmd(cli_h, (uint8_t *)"reboot", (callback_t) cli_cb_reboot); | ||
cli_add_cmd(cli_h, (uint8_t *)"disconnect", (callback_t) cli_cb_disconnect); | ||
cli_add_cmd(cli_h, (uint8_t *)"demo", (callback_t) cli_cb_clidemo); | ||
cli_add_cmd(cli_h, (uint8_t *)"setmotor", (callback_t) cli_cb_set_motor); | ||
cli_add_cmd(cli_h, (uint8_t *)"setmotors", (callback_t) cli_cb_set_motors); | ||
cli_add_cmd(cli_h, (uint8_t *)"stopmotors", (callback_t) cli_cb_stop_motors); | ||
cli_add_cmd(cli_h, (uint8_t *)"beepmotors", (callback_t) cli_cb_beep_motors); | ||
cli_add_cmd(cli_h, (uint8_t *)"setmotordir", (callback_t) cli_cb_set_motor_direction); | ||
cli_add_cmd(cli_h, (uint8_t *)"sendsc", (callback_t) cli_cb_sendsc); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// | ||
// Created by Isaak on 2/27/2024. | ||
// | ||
|
||
#ifndef BETTERFLIGHT_CLI_CMD_CALLBACKS_H | ||
#define BETTERFLIGHT_CLI_CMD_CALLBACKS_H | ||
|
||
#include "cli.h" | ||
|
||
void add_commands(cli_handle_t *cli_h); | ||
|
||
#endif //BETTERFLIGHT_CLI_CMD_CALLBACKS_H |
Oops, something went wrong.