application: add action to get/set individual USB pins

This commit is contained in:
King Kévin 2019-12-05 14:43:47 +01:00
parent 57de92d362
commit 29e0ec99df
1 changed files with 109 additions and 0 deletions

View File

@ -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)