From f5ab37ac99dd8a7b6abd2889af4a995409727db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Fri, 10 Jun 2022 00:04:36 +0900 Subject: [PATCH] Cli: cleanup gpio commands (#1306) * Cli: cleanup gpio commands * Cli: extra gpio message for debug pins --- applications/cli/cli_command_gpio.c | 228 ++++++++++++++++++++++++++++ applications/cli/cli_command_gpio.h | 5 + applications/cli/cli_commands.c | 186 +---------------------- 3 files changed, 236 insertions(+), 183 deletions(-) create mode 100644 applications/cli/cli_command_gpio.c create mode 100644 applications/cli/cli_command_gpio.h diff --git a/applications/cli/cli_command_gpio.c b/applications/cli/cli_command_gpio.c new file mode 100644 index 00000000..d5ec8d65 --- /dev/null +++ b/applications/cli/cli_command_gpio.c @@ -0,0 +1,228 @@ +#include "cli_command_gpio.h" + +#include +#include +#include + +typedef struct { + const GpioPin* pin; + const char* name; + const bool debug; +} CliCommandGpio; + +const CliCommandGpio cli_command_gpio_pins[] = { + {.pin = &gpio_ext_pc0, .name = "PC0", .debug = false}, + {.pin = &gpio_ext_pc1, .name = "PC1", .debug = false}, + {.pin = &gpio_ext_pc3, .name = "PC3", .debug = false}, + {.pin = &gpio_ext_pb2, .name = "PB2", .debug = false}, + {.pin = &gpio_ext_pb3, .name = "PB3", .debug = false}, + {.pin = &gpio_ext_pa4, .name = "PA4", .debug = false}, + {.pin = &gpio_ext_pa6, .name = "PA6", .debug = false}, + {.pin = &gpio_ext_pa7, .name = "PA7", .debug = false}, + /* Dangerous pins, may damage hardware */ + {.pin = &gpio_infrared_rx, .name = "PA0", .debug = true}, + {.pin = &gpio_usart_rx, .name = "PB7", .debug = true}, + {.pin = &gpio_speaker, .name = "PB8", .debug = true}, + {.pin = &gpio_infrared_tx, .name = "PB9", .debug = true}, +}; + +void cli_command_gpio_print_usage() { + printf("Usage:\r\n"); + printf("gpio \r\n"); + printf("Cmd list:\r\n"); + printf("\tmode <0|1>\t - Set gpio mode: 0 - input, 1 - output\r\n"); + printf("\tset <0|1>\t - Set gpio value\r\n"); + printf("\tread \t - Read gpio value\r\n"); +} + +static bool pin_name_to_int(string_t pin_name, size_t* result) { + bool found = false; + bool debug = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug); + for(size_t i = 0; i < COUNT_OF(cli_command_gpio_pins); i++) { + if(!string_cmp(pin_name, cli_command_gpio_pins[i].name)) { + if(!cli_command_gpio_pins[i].debug || (cli_command_gpio_pins[i].debug && debug)) { + *result = i; + found = true; + break; + } + } + } + + return found; +} + +static void gpio_print_pins(void) { + printf("Wrong pin name. Available pins: "); + bool debug = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug); + for(size_t i = 0; i < COUNT_OF(cli_command_gpio_pins); i++) { + if(!cli_command_gpio_pins[i].debug || (cli_command_gpio_pins[i].debug && debug)) { + printf("%s ", cli_command_gpio_pins[i].name); + } + } +} + +typedef enum { OK, ERR_CMD_SYNTAX, ERR_PIN, ERR_VALUE } GpioParseError; + +static GpioParseError gpio_command_parse(string_t args, size_t* pin_num, uint8_t* value) { + string_t pin_name; + string_init(pin_name); + + size_t ws = string_search_char(args, ' '); + if(ws == STRING_FAILURE) { + return ERR_CMD_SYNTAX; + } + + string_set_n(pin_name, args, 0, ws); + string_right(args, ws); + string_strim(args); + + if(!pin_name_to_int(pin_name, pin_num)) { + string_clear(pin_name); + return ERR_PIN; + } + + string_clear(pin_name); + + if(!string_cmp(args, "0")) { + *value = 0; + } else if(!string_cmp(args, "1")) { + *value = 1; + } else { + return ERR_VALUE; + } + + return OK; +} + +void cli_command_gpio_mode(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(context); + + size_t num = 0; + uint8_t value = 255; + + GpioParseError err = gpio_command_parse(args, &num, &value); + + if(ERR_CMD_SYNTAX == err) { + cli_print_usage("gpio mode", " <0|1>", string_get_cstr(args)); + return; + } else if(ERR_PIN == err) { + gpio_print_pins(); + return; + } else if(ERR_VALUE == err) { + printf("Value is invalid. Enter 1 for input or 0 for output"); + return; + } + + if(cli_command_gpio_pins[num].debug) { + printf( + "Changeing this pin mode may damage hardware. Are you sure you want to continue? (y/n)?\r\n"); + char c = cli_getc(cli); + if(c != 'y' && c != 'Y') { + printf("Cancelled.\r\n"); + return; + } + } + + if(value == 1) { // output + furi_hal_gpio_write(cli_command_gpio_pins[num].pin, false); + furi_hal_gpio_init_simple(cli_command_gpio_pins[num].pin, GpioModeOutputPushPull); + printf("Pin %s is now an output (low)", cli_command_gpio_pins[num].name); + } else { // input + furi_hal_gpio_init_simple(cli_command_gpio_pins[num].pin, GpioModeInput); + printf("Pin %s is now an input", cli_command_gpio_pins[num].name); + } +} + +void cli_command_gpio_read(Cli* cli, string_t args, void* context) { + UNUSED(cli); + UNUSED(context); + + size_t num = 0; + if(!pin_name_to_int(args, &num)) { + gpio_print_pins(); + return; + } + + if(LL_GPIO_MODE_INPUT != + LL_GPIO_GetPinMode( + cli_command_gpio_pins[num].pin->port, cli_command_gpio_pins[num].pin->pin)) { + printf("Err: pin %s is not set as an input.", cli_command_gpio_pins[num].name); + return; + } + + uint8_t val = !!furi_hal_gpio_read(cli_command_gpio_pins[num].pin); + + printf("Pin %s <= %u", cli_command_gpio_pins[num].name, val); +} + +void cli_command_gpio_set(Cli* cli, string_t args, void* context) { + UNUSED(context); + + size_t num = 0; + uint8_t value = 0; + GpioParseError err = gpio_command_parse(args, &num, &value); + + if(ERR_CMD_SYNTAX == err) { + cli_print_usage("gpio set", " <0|1>", string_get_cstr(args)); + return; + } else if(ERR_PIN == err) { + gpio_print_pins(); + return; + } else if(ERR_VALUE == err) { + printf("Value is invalid. Enter 1 for high or 0 for low"); + return; + } + + if(LL_GPIO_MODE_OUTPUT != + LL_GPIO_GetPinMode( + cli_command_gpio_pins[num].pin->port, cli_command_gpio_pins[num].pin->pin)) { + printf("Err: pin %s is not set as an output.", cli_command_gpio_pins[num].name); + return; + } + + // Extra check if debug pins used + if(cli_command_gpio_pins[num].debug) { + printf( + "Setting this pin may damage hardware. Are you sure you want to continue? (y/n)?\r\n"); + char c = cli_getc(cli); + if(c != 'y' && c != 'Y') { + printf("Cancelled.\r\n"); + return; + } + } + + furi_hal_gpio_write(cli_command_gpio_pins[num].pin, !!value); + printf("Pin %s => %u", cli_command_gpio_pins[num].name, !!value); +} + +void cli_command_gpio(Cli* cli, string_t args, void* context) { + string_t cmd; + string_init(cmd); + + do { + if(!args_read_string_and_trim(args, cmd)) { + cli_command_gpio_print_usage(); + break; + } + + if(string_cmp_str(cmd, "mode") == 0) { + cli_command_gpio_mode(cli, args, context); + break; + } + + if(string_cmp_str(cmd, "set") == 0) { + cli_command_gpio_set(cli, args, context); + break; + } + + if(string_cmp_str(cmd, "read") == 0) { + cli_command_gpio_read(cli, args, context); + break; + } + + cli_command_gpio_print_usage(); + } while(false); + + string_clear(cmd); +} diff --git a/applications/cli/cli_command_gpio.h b/applications/cli/cli_command_gpio.h new file mode 100644 index 00000000..c9b908a0 --- /dev/null +++ b/applications/cli/cli_command_gpio.h @@ -0,0 +1,5 @@ +#pragma once + +#include "cli_i.h" + +void cli_command_gpio(Cli* cli, string_t args, void* context); diff --git a/applications/cli/cli_commands.c b/applications/cli/cli_commands.c index 47ee3b4f..8271ab31 100644 --- a/applications/cli/cli_commands.c +++ b/applications/cli/cli_commands.c @@ -1,6 +1,7 @@ #include "cli_commands.h" +#include "cli_command_gpio.h" + #include -#include #include #include #include @@ -248,185 +249,6 @@ void cli_command_led(Cli* cli, string_t args, void* context) { furi_record_close("notification"); } -char pin_names[][4] = { - "PC0", - "PC1", - "PC3", - "PB2", - "PB3", - "PA4", - "PA6", - "PA7", -#ifdef FURI_DEBUG - "PA0", - "PB7", - "PB8", - "PB9" -#endif -}; -GpioPin gpio[] = { - {.port = GPIOC, .pin = LL_GPIO_PIN_0}, - {.port = GPIOC, .pin = LL_GPIO_PIN_1}, - {.port = GPIOC, .pin = LL_GPIO_PIN_3}, - {.port = GPIOB, .pin = LL_GPIO_PIN_2}, - {.port = GPIOB, .pin = LL_GPIO_PIN_3}, - {.port = GPIOA, .pin = LL_GPIO_PIN_4}, - {.port = GPIOA, .pin = LL_GPIO_PIN_6}, - {.port = GPIOA, .pin = LL_GPIO_PIN_7}, -#ifdef FURI_DEBUG - {.port = GPIOA, .pin = LL_GPIO_PIN_0}, // IR_RX (PA0) - {.port = GPIOB, .pin = LL_GPIO_PIN_7}, // UART RX (PB7) - {.port = GPIOB, .pin = LL_GPIO_PIN_8}, // SPEAKER (PB8) - {.port = GPIOB, .pin = LL_GPIO_PIN_9}, // IR_TX (PB9) -#endif -}; - -static bool pin_name_to_int(string_t pin_name, uint8_t* result) { - uint8_t num = 0; - bool pin_found = false; - - for(num = 0; num < sizeof(pin_names) / sizeof(char*); num++) { - if(!string_cmp(pin_name, pin_names[num])) { - pin_found = true; - break; - } - } - - *result = num; - return pin_found; -} - -static void gpio_print_pins(void) { - printf("Wrong pin name. Available pins: "); - for(uint8_t i = 0; i < sizeof(pin_names) / sizeof(char*); i++) { - printf("%s ", pin_names[i]); - } -} - -typedef enum { OK, ERR_CMD_SYNTAX, ERR_PIN, ERR_VALUE } GpioParseError; - -static GpioParseError gpio_command_parse(string_t args, uint8_t* pin_num, uint8_t* value) { - string_t pin_name; - string_init(pin_name); - - size_t ws = string_search_char(args, ' '); - if(ws == STRING_FAILURE) { - return ERR_CMD_SYNTAX; - } - - string_set_n(pin_name, args, 0, ws); - string_right(args, ws); - string_strim(args); - - if(!pin_name_to_int(pin_name, pin_num)) { - string_clear(pin_name); - return ERR_PIN; - } - - string_clear(pin_name); - - if(!string_cmp(args, "0")) { - *value = 0; - } else if(!string_cmp(args, "1")) { - *value = 1; - } else { - return ERR_VALUE; - } - - return OK; -} - -void cli_command_gpio_mode(Cli* cli, string_t args, void* context) { - UNUSED(cli); - UNUSED(context); - - uint8_t num = 0; - uint8_t value = 255; - - GpioParseError err = gpio_command_parse(args, &num, &value); - - if(ERR_CMD_SYNTAX == err) { - cli_print_usage("gpio_mode", " <0|1>", string_get_cstr(args)); - return; - } else if(ERR_PIN == err) { - gpio_print_pins(); - return; - } else if(ERR_VALUE == err) { - printf("Value is invalid. Enter 1 for input or 0 for output"); - return; - } - - if(value == 0) { // output - furi_hal_gpio_init_simple(gpio + num, GpioModeOutputPushPull); - furi_hal_gpio_write(gpio + num, false); - printf("Pin %s is now an output (low)", pin_names[num]); - } else { // input - furi_hal_gpio_init_simple(gpio + num, GpioModeInput); - printf("Pin %s is now an input", pin_names[num]); - } -} - -void cli_command_gpio_read(Cli* cli, string_t args, void* context) { - UNUSED(cli); - UNUSED(context); - - uint8_t num = 0; - if(!pin_name_to_int(args, &num)) { - gpio_print_pins(); - return; - } - - if(LL_GPIO_MODE_INPUT != LL_GPIO_GetPinMode(gpio[num].port, gpio[num].pin)) { - printf("Err: pin %s is not set as an input.", pin_names[num]); - return; - } - - uint8_t val = !!furi_hal_gpio_read(&gpio[num]); - - printf("Pin %s <= %u", pin_names[num], val); -} - -void cli_command_gpio_set(Cli* cli, string_t args, void* context) { - UNUSED(context); - - uint8_t num = 0; - uint8_t value = 0; - GpioParseError err = gpio_command_parse(args, &num, &value); - - if(ERR_CMD_SYNTAX == err) { - cli_print_usage("gpio_set", " <0|1>", string_get_cstr(args)); - return; - } else if(ERR_PIN == err) { - gpio_print_pins(); - return; - } else if(ERR_VALUE == err) { - printf("Value is invalid. Enter 1 for high or 0 for low"); - return; - } - - if(LL_GPIO_MODE_OUTPUT != LL_GPIO_GetPinMode(gpio[num].port, gpio[num].pin)) { - printf("Err: pin %s is not set as an output.", pin_names[num]); - return; - } - -#ifdef FURI_DEBUG - if(value && num == 8) { // PA0 - printf( - "Setting PA0 pin HIGH with TSOP connected can damage IR receiver. Are you sure you want to continue? (y/n)?\r\n"); - char c = cli_getc(cli); - if(c != 'y' && c != 'Y') { - printf("Cancelled.\r\n"); - return; - } - } -#else - UNUSED(cli); -#endif - - furi_hal_gpio_write(gpio + num, !!value); - printf("Pin %s => %u", pin_names[num], !!value); -} - void cli_command_ps(Cli* cli, string_t args, void* context) { UNUSED(cli); UNUSED(args); @@ -508,8 +330,6 @@ void cli_commands_init(Cli* cli) { cli_add_command(cli, "vibro", CliCommandFlagDefault, cli_command_vibro, NULL); cli_add_command(cli, "led", CliCommandFlagDefault, cli_command_led, NULL); - cli_add_command(cli, "gpio_mode", CliCommandFlagDefault, cli_command_gpio_mode, NULL); - cli_add_command(cli, "gpio_read", CliCommandFlagDefault, cli_command_gpio_read, NULL); - cli_add_command(cli, "gpio_set", CliCommandFlagDefault, cli_command_gpio_set, NULL); + cli_add_command(cli, "gpio", CliCommandFlagDefault, cli_command_gpio, NULL); cli_add_command(cli, "i2c", CliCommandFlagDefault, cli_command_i2c, NULL); }