diff --git a/hooks/pre-commit b/hooks/pre-commit old mode 100644 new mode 100755 diff --git a/projects/uart_cli/inc/adc_cli.h b/projects/uart_cli/inc/adc_cli.h new file mode 100644 index 000000000..30eadb2ee --- /dev/null +++ b/projects/uart_cli/inc/adc_cli.h @@ -0,0 +1,11 @@ +#pragma once +#include + +#include "cli_base.h" + +void adc_cmd(char *input); + +bool adc_valid_addr(char *port); +bool adc_valid_state(char *state); +int adc_valid_pin_mode(char *pin_mode); +bool adc_state_to_int(char *state); diff --git a/projects/uart_cli/inc/cli.h b/projects/uart_cli/inc/cli.h index 7bcef584e..119697667 100644 --- a/projects/uart_cli/inc/cli.h +++ b/projects/uart_cli/inc/cli.h @@ -16,6 +16,7 @@ the keyword for an action to the corresponding prv function */ #include "gpio_cli.h" +#include "adc_cli.h" void cli_init(); void cli_run(); diff --git a/projects/uart_cli/src/adc_cli.c b/projects/uart_cli/src/adc_cli.c new file mode 100644 index 000000000..965496224 --- /dev/null +++ b/projects/uart_cli/src/adc_cli.c @@ -0,0 +1,236 @@ +#include "adc_cli.h" + +#include +#include +#include + +#include "adc.h" +#include "log.h" +#include "string.h" + +static const char adc_help[] = + "CLI Reference for GPIO Pins. Usage: \n\r" + "adc \n\r\n" + + "Commands:\n\r" + " - add: Initialize an ADC channel\n\r" + " - run: Start ADC conversions on all initialized channels\n\r" + " - raw: Read raw ADC values from a specified channel\n\r" + " - converted: Read converted (processed) ADC values\n\r\n" + + "Type \"help\" after any action for detailed reference.\n\r"; + +static const char adc_add_help[] = + "Usage: Add an ADC channel by specifying the pin and mode. \n\r" + "adc add
\n\r\n" + + "Address: \n\r" + "Examples: A0, A7, B1\n\r\n" + + "Pin Modes: \"analog\", \"input_floating\", \"input_pull_down\", \n\r" + "\"input_pull_up\", \"output_open_drain\", \"output_push_pull\", \n\r" + "\"altfn_open_drain\", \"altfn_push_pull\" \n\r\n" + + "Example: adc add A0 analog\n\r"; + +static const char adc_run_help[] = + "Usage: Start ADC conversions on all initialized channels. \n\r" + "adc run\n\r"; + +static const char adc_read_converted_help[] = + "Usage: Read converted (processed) ADC values from the specified channel. \n\r" + "adc converted
\n\r\n" + + "Address: \n\r" + "Example: adc converted A0\n\r"; + +static const char adc_read_raw_help[] = + "Usage: Read raw ADC values from the specified channel. \n\r" + "adc raw
\n\r\n" + + "Address: \n\r" + "Example: adc raw A0\n\r"; + +static void prv_add_channel(char *args) { + char addr[MAX_CMD_LEN + 1] = { 0 }; + tok_cmd(args, addr); + char pin_mode[MAX_CMD_LEN + 1] = { 0 }; + tok_cmd(args, pin_mode); + + int pin_mode_enum = adc_valid_pin_mode(pin_mode); + char *state_str = args; + + if (strcmp(addr, "help") == 0 || strcmp(addr, "h") == 0) { + printf("\r%s\n", adc_add_help); + return; + } else if (!(adc_valid_addr(addr) && adc_valid_state(state_str))) { + printf("\r%s\n", adc_add_help); + return; + } else if (!(adc_valid_addr(addr) && (pin_mode_enum != NUM_GPIO_MODES) && + adc_valid_pin_port(state_str))) { + printf("Invalid pin mode\n\r"); + printf("\r%s\n", adc_add_help); + return; + } + + GpioAddress address = { .port = addr[0] - 97, .pin = strtol(addr + 1, NULL, 10) }; + + if (adc_add_channel(address) == STATUS_CODE_OK) { + printf("SUCCESS\n\r"); + } else { + printf("FAILED\n\r"); + } +} + +static void prv_run(char *args) { + char addr[MAX_CMD_LEN + 1] = { 0 }; + tok_cmd(args, addr); + + if (strcmp(addr, "help") == 0 || strcmp(addr, "h") == 0) { + printf("\r%s\n", adc_run_help); + return; + } + + if (adc_run() == STATUS_CODE_OK) { + printf("SUCCESS\n\r"); + } else { + printf("FAILED\n\r"); + } +} + +static void prv_read_raw(char *args) { + char *addr = args; + char pin_mode[MAX_CMD_LEN + 1] = { 0 }; + tok_cmd(args, pin_mode); + + int pin_mode_enum = adc_valid_pin_mode(pin_mode); + char *state_str = args; + + if (strcmp(addr, "help") == 0 || strcmp(addr, "h") == 0) { + printf("\r%s\n", adc_read_raw_help); + return; + } else if (!adc_valid_addr(addr)) { + printf("\r%s\n", adc_read_raw_help); + return; + } else if (!(adc_valid_addr(addr) && (pin_mode_enum != NUM_GPIO_MODES) && + adc_valid_pin_port(state_str))) { + printf("Invalid pin mode\n\r"); + printf("\r%s\n", adc_read_raw_help); + return; + } + + GpioAddress address = { .port = addr[0] - 97, .pin = strtol(addr + 1, NULL, 10) }; + uint16_t reading; + + if (adc_read_raw(address, &reading) == STATUS_CODE_OK) { + printf("\r%d\n", reading); + } else { + printf("FAILED\n\r"); + } +} + +static void prv_read_converted(char *args) { + char *addr = args; + char pin_mode[MAX_CMD_LEN + 1] = { 0 }; + tok_cmd(args, pin_mode); + + int pin_mode_enum = adc_valid_pin_mode(pin_mode); + char *state_str = args; + + if (strcmp(args, "help") == 0 || strcmp(args, "h") == 0) { + printf("\r%s\n", adc_read_converted_help); + return; + } else if (!(adc_valid_addr(args))) { + printf("\r%s\n", adc_read_converted_help); + return; + } else if (!(adc_valid_addr(addr) && (pin_mode_enum != NUM_GPIO_MODES) && + adc_valid_pin_port(state_str))) { + printf("Invalid pin mode\n\r"); + printf("\r%s\n", adc_read_converted_help); + return; + } + + GpioAddress address = { .port = args[0] - 97, .pin = strtol(args + 1, NULL, 10) }; + uint16_t reading; + + if (adc_read_converted(address, &reading) == STATUS_CODE_OK) { + printf("\r%d\n", reading); + } else { + printf("FAILED\n\r"); + } +} + +bool adc_valid_addr(char *addr) { + if (addr[0] < 97 || addr[0] > 103) { + printf("Invalid port - must be a value from a to g\n\r"); + return false; + } + + char *end_ptr = NULL; + const uint8_t pin = strtol(addr + 1, &end_ptr, 10); + + if (pin > 15 || *end_ptr != '\0') { + printf("Invalid pin - must be a value from 0 to 15\n\r"); + return false; + } + + return true; +} + +//Replace with valid adc pin +//Assuming we're using STM32F103C8T6 which has PA0-PA7, PB0, PB1 as ADC pins +bool adc_valid_pin_port(char *state_str) { + char port = strtol(state_str[1], NULL, 10); + char pin = state_str[0] - 97; + if (port == 'A' && pin >= 0 && pin < 8) { + return true; + } + if (port == 'B' && pin >= 0 && pin < 2) { + return true; + } + return false; +} + +int adc_valid_pin_mode(char *pin_mode) { + const char *pin_modes[NUM_GPIO_MODES] = { + "analog", "input_floating", "input_pull_down", "input_pull_up", "output_open_drain", + "output_push_pull", "alftn_open_drain", "altfn_push_pull" + }; + + for (int i = 0; i < NUM_GPIO_MODES; ++i) { + if (strcmp(pin_mode, pin_modes[i]) == 0) { + return i; + } + } + return NUM_GPIO_MODES; +} + +bool adc_state_to_int(char *state) { + return strcmp(state, "low"); +} + +static const CmdStruct adc_lookup[] = { { .cmd_name = "add", .cmd_func = &prv_add_channel }, + { .cmd_name = "run", .cmd_func = &prv_run }, + { .cmd_name = "raw", .cmd_func = &prv_read_raw }, + { .cmd_name = "converted", + .cmd_func = &prv_read_converted } }; + +void adc_cmd(char *cmd) { + char action[MAX_CMD_LEN + 1] = { 0 }; + tok_cmd(cmd, action); + + if (strcmp(action, "help") == 0 || strcmp(action, "h") == 0) { + printf("\r%s\n", adc_help); + return; + } + + for (size_t i = 0; i < SIZEOF_ARRAY(adc_lookup); ++i) { + if (strcmp(action, adc_lookup[i].cmd_name) == 0) { + adc_lookup[i].cmd_func(cmd); + return; + } + } + // ERROR: Invalid action + printf("Invalid action\n\r"); + printf("\r%s\n", adc_help); +} diff --git a/projects/uart_cli/src/cli.c b/projects/uart_cli/src/cli.c index 5a8826206..31ed2584f 100644 --- a/projects/uart_cli/src/cli.c +++ b/projects/uart_cli/src/cli.c @@ -17,7 +17,8 @@ static const char cli_help[] = static char cmd_buffer[MAX_CMD_LEN + 1]; // Add additional peripherals to lookup array -static const CmdStruct cmd_lookup[] = { { .cmd_name = "gpio", .cmd_func = &gpio_cmd } }; +static const CmdStruct cmd_lookup[] = { { .cmd_name = "gpio", .cmd_func = &gpio_cmd }, + {.cmd_name = "adc", .cmd_func = &adc_cmd} }; void cli_init() { // Add peripheral init calls here