application: add action to get/set individual USB pins
This commit is contained in:
parent
57de92d362
commit
29e0ec99df
109
application.c
109
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)
|
||||
|
|
Loading…
Reference in New Issue