From 29e0ec99dfa362e95e55a7de2146c91ea2c32c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Thu, 5 Dec 2019 14:43:47 +0100 Subject: [PATCH] application: add action to get/set individual USB pins --- application.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/application.c b/application.c index 285e9ec..6201d9a 100644 --- a/application.c +++ b/application.c @@ -254,6 +254,107 @@ static void command_find(void* argument) usb_pins_float(); // put all pins back in safe floating state } +/** set or show pin value + * @param[in] argument pin number and level + */ +static void command_pin(void* argument) +{ + char* pin_str = NULL; // to parse the pin number + char* pin_level = NULL; // to parse the pin level + const char* delimiter = " "; // words are separated by spaces + uint8_t pin_nb = 0; // parsed pin number + if (argument) { // pin number and level might have been provided + pin_str = strtok((char*)argument, delimiter); // get pin number string + if (pin_str) { + pin_nb = strtoul(pin_str, NULL, 10); // parse pin number + pin_level = strtok(NULL, delimiter); // get pin level + } + } + + // print header + if (!pin_level) { + printf("pin state (H: out high, L: out low, h in high, l in low, x in floating):\n"); + } else { + printf("setting pin\n"); + } + uint8_t pin_i = 0; // current pin + for (uint8_t connector = 0; connector < LENGTH(usb_connectors); connector++) { // test every connector + bool connector_print = (!pin_str || (!pin_level && pin_nb >= pin_i && pin_nb < pin_i + usb_connectors[connector]->pins_nb)); // if a pin information will be printed for this connector + if (connector_print) { + printf("%s (%s):\n", usb_connectors[connector]->name, usb_connectors[connector]->host ? "host" : "device"); // print connector name + } + for (uint8_t pin = 0; pin < usb_connectors[connector]->pins_nb; pin++) { // test every pin + uint32_t pin_port = usb_connectors[connector]->pins[pin].port; // GPIO port corresponding to USB pin + uint16_t pin_pin = usb_connectors[connector]->pins[pin].pin; // GPIO pin corresponding to USB pin + if (!pin_str || (!pin_level && pin_nb == pin_i)) { // show pin state + printf("%03u %s: ", pin_i, usb_connectors[connector]->pins[pin].name); // print USB pin number + uint8_t offset = (pin_pin < 8) ? (pin_pin * 4) : ((pin_pin - 8) * 4); // get pin offset within port + uint8_t mode = ((pin_pin < 8) ? GPIO_CRL(pin_port) : GPIO_CRH(pin_port) >> offset) & 0x3; // get mode from pin for port + // only show the actual value, not the one set + if (0 == mode) { // pin is configured as input + // TODO test only if input is set to floating + gpio_set_mode(pin_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, pin_pin); // we will test if the input is floating by checking against a pull up and down + gpio_set(pin_port, pin_pin); // pull up + sleep_us(10); // wait for GPIO/line to settle + bool high = (0 != gpio_get(pin_port, pin_pin)); // test if pin is high + gpio_clear(pin_port, pin_pin); // pull down + sleep_us(10); // wait for GPIO/line to settle + bool low = (0 == gpio_get(pin_port, pin_pin)); // test if pin is low + gpio_set_mode(pin_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, pin_pin); // put back to floating + // check and display result + if (high && !low) { // pull down did not work + putc('h'); // something is driving the pin high + } else if (!high && low) { // pull up did not work + putc('l'); // something is driving the pin low + } else if (high && low) { // pull up and down worked + putc('x'); // nothing is driving the pin + } else { // pull up and down did not work + putc('?'); // something is driving the pin randomly + } + } else { // pin is configured as output + // only show the actual measured output, not the one set + if (gpio_get(pin_port, pin_pin)) { + putc('H'); // pin is high + } else { + putc('L'); // pin is low + } + } + putc('\n'); + } + if (pin_level && pin_nb == pin_i) { // set pin + printf("%03u %s: %s", pin_i, usb_connectors[connector]->pins[pin].name, pin_level); + switch (pin_level[0]) { + case 'h': + gpio_set(pin_port, pin_pin); + gpio_set_mode(pin_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, pin_pin); + break; + case 'H': + gpio_set(pin_port, pin_pin); + gpio_set_mode(pin_port, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, pin_pin); + break; + case 'l': + gpio_clear(pin_port, pin_pin); + gpio_set_mode(pin_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, pin_pin); + break; + case 'L': + gpio_clear(pin_port, pin_pin); + gpio_set_mode(pin_port, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, pin_pin); + break; + case 'x': + case 'X': + default: + gpio_set_mode(pin_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, pin_pin); + } + putc('\n'); + } + pin_i++; // increase global pin number + } // pin + if (connector_print) { + putc('\n'); // separate connectors for readability + } + } // connector +} + /** list of all supported commands */ static const struct menu_command_t menu_commands[] = { { @@ -338,6 +439,14 @@ static const struct menu_command_t menu_commands[] = { .argument_description = NULL, .command_handler = &command_find, }, + { + .shortcut = 'p', + .name = "pin", + .command_description = "set/show pin level", + .argument = MENU_ARGUMENT_STRING, + .argument_description = "[nb] [H/L/h/l/x]", + .command_handler = &command_pin, + }, }; static void command_help(void* argument)