usb_cables: improve mechanism to find if pins are conencted
This commit is contained in:
parent
e4b8be4e5a
commit
4262e90792
127
usb_cables.c
127
usb_cables.c
|
@ -1366,75 +1366,71 @@ void usb_cables_connectors_float(const struct usb_connector_t** connectors, uint
|
|||
}
|
||||
}
|
||||
|
||||
/** test if two pins are connected
|
||||
* @param[in] pin1_port GPIO port for first pin
|
||||
* @param[in] pin1_pin GPIO pin for first pin
|
||||
* @param[in] pin2_port GPIO port for first pin
|
||||
* @param[in] pin2_pin GPIO pin for first pin
|
||||
* @return if there is any kind of connection between the pins
|
||||
* @note setting both levels (high, low) in both directions (pin1 to pin2 and pin2 to pin1) is tested, except for ground pins
|
||||
* @warning this is prone to false positives
|
||||
*/
|
||||
static bool usb_cables_check_pins(const struct usb_pin_t* pin1, const struct usb_pin_t* pin2)
|
||||
uint8_t usb_cables_check_pins(const struct usb_pin_t* pin1, const struct usb_pin_t* pin2)
|
||||
{
|
||||
cm3_assert(pin1 && pin2);
|
||||
|
||||
if (pin1->port == pin2->port && pin1->pin == pin2->pin) { // it's the same pin
|
||||
return true;
|
||||
return 0xff; // all connections will work
|
||||
}
|
||||
|
||||
uint8_t connections = 0; // numbers of connection configurations
|
||||
|
||||
gpio_set_mode(pin2->port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, pin2->pin); // we will read from this pin
|
||||
gpio_set(pin2->port, pin2->pin); // pull up
|
||||
gpio_clear(pin1->port, pin1->pin); // drive low
|
||||
gpio_set_mode(pin1->port, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, pin1->pin); // we will drive this pin
|
||||
sleep_us(100); // wait for GPIO/line to settle
|
||||
if (!gpio_get(pin1->port, pin1->pin) && !gpio_get(pin2->port, pin2->pin)) { // if they are at the same level it means pin2 was able to drive low the pulled up pin1, thus they are connected
|
||||
connections++;
|
||||
}
|
||||
|
||||
if (USB_PIN_TYPE_GROUND != pin1->type) { // don't drive a ground pin high
|
||||
gpio_set_mode(pin2->port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, pin2->pin); // we will read from this pin
|
||||
gpio_clear(pin2->port, pin2->pin); // pull down
|
||||
gpio_set(pin1->port, pin1->pin); // drive high
|
||||
gpio_set_mode(pin1->port, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, pin1->pin); // we will drive this pin
|
||||
sleep_us(100); // wait for GPIO/line to settle
|
||||
if (gpio_get(pin1->port, pin1->pin) && gpio_get(pin2->port, pin2->pin)) { // if they are at the same level it means pin2 was able to drive high the pulled low pin1, thus they are connected
|
||||
connections++;
|
||||
uint8_t connection = 0; // the connection result to return
|
||||
for (uint8_t direction = 0; direction < 2; direction++) { // test both directions
|
||||
uint32_t from_port = (0 == direction ? pin2->port : pin1->port);
|
||||
uint16_t from_pin = (0 == direction ? pin2->pin : pin1->pin);
|
||||
uint32_t to_port = (0 == direction ? pin1->port : pin2->port);
|
||||
uint16_t to_pin = (0 == direction ? pin1->pin : pin2->pin);
|
||||
for (uint8_t mode = 0; mode < 3; mode++) { // test all connection types
|
||||
// don't drive a ground pin high
|
||||
if (((0 == direction && USB_PIN_TYPE_GROUND == pin2->type) || (1 == direction && USB_PIN_TYPE_GROUND == pin1->type)) && (0 == mode || 1 == mode)) {
|
||||
continue;
|
||||
}
|
||||
// set pin mode
|
||||
switch (mode) {
|
||||
case 0:
|
||||
gpio_set_mode(from_port, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, from_pin);
|
||||
gpio_set_mode(to_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, to_pin);
|
||||
break;
|
||||
case 1:
|
||||
gpio_set_mode(from_port, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, from_pin);
|
||||
gpio_set_mode(to_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, to_pin);
|
||||
break;
|
||||
case 2:
|
||||
gpio_set_mode(from_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, from_pin);
|
||||
gpio_set_mode(to_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, to_pin);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// test pattern
|
||||
bool connected = true;
|
||||
for (uint8_t pattern = 0; pattern < 8 && connected; pattern++) {
|
||||
if (0 == pattern % 2) {
|
||||
gpio_clear(from_port, from_pin);
|
||||
gpio_set(to_port, to_pin);
|
||||
sleep_us(25); // wait for GPIO/line to settle
|
||||
if (gpio_get(to_port, to_pin)) {
|
||||
connected = false;
|
||||
}
|
||||
} else {
|
||||
gpio_set(from_port, from_pin);
|
||||
gpio_clear(to_port, to_pin);
|
||||
sleep_us(25); // wait for GPIO/line to settle
|
||||
if (0 == gpio_get(to_port, to_pin)) {
|
||||
connected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (connected) {
|
||||
connection |= ((1 << mode) << (direction * 4));
|
||||
}
|
||||
}
|
||||
// put back to floating
|
||||
gpio_set_mode(from_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, from_pin);
|
||||
gpio_set_mode(to_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, to_pin);
|
||||
}
|
||||
|
||||
gpio_set_mode(pin1->port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, pin1->pin); // we will read from this pin
|
||||
gpio_set(pin1->port, pin1->pin); // pull up
|
||||
gpio_clear(pin2->port, pin2->pin); // drive low
|
||||
gpio_set_mode(pin2->port, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, pin2->pin); // we will drive this pin
|
||||
sleep_us(100); // wait for GPIO/line to settle
|
||||
if (!gpio_get(pin1->port, pin1->pin) && !gpio_get(pin2->port, pin2->pin)) { // if they are at the same level it means pin1 was able to drive low the pulled up pin2, thus they are connected
|
||||
connections++;
|
||||
}
|
||||
|
||||
if (USB_PIN_TYPE_GROUND != pin2->type) {
|
||||
gpio_set_mode(pin1->port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, pin1->pin); // we will read from this pin
|
||||
gpio_clear(pin1->port, pin1->pin); // pull down
|
||||
gpio_set(pin2->port, pin2->pin); // drive high
|
||||
gpio_set_mode(pin2->port, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, pin2->pin); // we will drive this pin
|
||||
sleep_us(100); // wait for GPIO/line to settle
|
||||
if (gpio_get(pin1->port, pin1->pin) && gpio_get(pin2->port, pin2->pin)) { // if they are at the same level it means pin1 was able to drive high the pulled low pin2, thus they are connected
|
||||
connections++;
|
||||
}
|
||||
}
|
||||
|
||||
gpio_set_mode(pin1->port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, pin1->pin); // put pin back to safe floating state
|
||||
gpio_set_mode(pin2->port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, pin2->pin); // put pin back to safe floating state
|
||||
|
||||
if (0 == connections) {
|
||||
return 0; // no connections
|
||||
} else if (4 == connections) {
|
||||
return 1; // full connection
|
||||
} else {
|
||||
return -connections; // partial connection
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
void usb_cables_check_intra(const struct usb_connector_t* connector, bool* connected)
|
||||
|
@ -1465,12 +1461,13 @@ void usb_cables_check_intra(const struct usb_connector_t* connector, bool* conne
|
|||
continue;
|
||||
}
|
||||
|
||||
if (usb_cables_check_pins(&connector->pins[pin_from], &connector->pins[pin_to])) {
|
||||
uint8_t connection = usb_cables_check_pins(&connector->pins[pin_from], &connector->pins[pin_to]);
|
||||
if (connection >= 0x44) {
|
||||
if (connected) {
|
||||
connected[pin_from] = true;
|
||||
connected[pin_to] = true;
|
||||
} else {
|
||||
printf("%s (%s) %s connected to %s\n", connector->name, connector->host ? "host" : "device", connector->pins[pin_from].name, connector->pins[pin_to].name);
|
||||
printf("%s (%s) %s connected to %s (%02x)\n", connector->name, connector->host ? "host" : "device", connector->pins[pin_from].name, connector->pins[pin_to].name, connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1512,7 +1509,8 @@ void usb_cables_check_inter(const struct usb_connector_t** connectors, uint8_t c
|
|||
continue;
|
||||
}
|
||||
// check if cable is connected
|
||||
if (usb_cables_check_pins(&connectors[connector_from]->pins[pin_from], &connectors[connector_to]->pins[pin_to])) {
|
||||
uint8_t connection = usb_cables_check_pins(&connectors[connector_from]->pins[pin_from], &connectors[connector_to]->pins[pin_to]);
|
||||
if (connection >= 0x44) {
|
||||
if (connected) { // remember they are connected
|
||||
connected[connector_from] = true;
|
||||
connected[connector_to] = true;
|
||||
|
@ -1685,7 +1683,8 @@ bool usb_cables_check_cable(const struct usb_cable_t* usb_cable, uint8_t* define
|
|||
}
|
||||
}
|
||||
|
||||
if (usb_cables_check_pins(&usb_cable->connectors[connector_from]->pins[pin_from], &usb_cable->connectors[connector_to]->pins[pin_to])) { // the connection is fine
|
||||
uint8_t connection = usb_cables_check_pins(&usb_cable->connectors[connector_from]->pins[pin_from], &usb_cable->connectors[connector_to]->pins[pin_to]);
|
||||
if (connection >= 0x44) {
|
||||
if (pair_defined) {
|
||||
_defined++;
|
||||
} else {
|
||||
|
|
18
usb_cables.h
18
usb_cables.h
|
@ -28,7 +28,16 @@ enum usb_pin_type_t {
|
|||
USB_PIN_TYPE_OTHER,
|
||||
};
|
||||
|
||||
/* USB pin definition */
|
||||
/** the type of connection between two pins
|
||||
* @note to be used as bit mask
|
||||
*/
|
||||
enum usb_pin_connection_t {
|
||||
USB_PIN_CONNECTION_DRIVE_FLOAT = (1 << 0), /*< the output side is driven using pull/push, the input is floating */
|
||||
USB_PIN_CONNECTION_DRIVE_PULL = (1 << 1), /*< the output side is driven using pull/push, the input is pulled up/down */
|
||||
USB_PIN_CONNECTION_PULL_FLOAT = (1 << 2), /*< the output side is driven using pull up/down, the input is floating */
|
||||
};
|
||||
|
||||
/** USB pin definition */
|
||||
struct usb_pin_t {
|
||||
const char* name; /*< pin name */
|
||||
uint32_t port; /*< on which MCU port is this pin connected */
|
||||
|
@ -67,6 +76,13 @@ void usb_cables_pins_float(const struct usb_connector_t* connector);
|
|||
* @param[in] connectors_nb numbers of connectors
|
||||
*/
|
||||
void usb_cables_connectors_float(const struct usb_connector_t** connectors, uint8_t connectors_nb);
|
||||
/** test if two pins are connected
|
||||
* @param[in] pin1 first pin
|
||||
* @param[in] pin2 second pin
|
||||
* @return first nibble corresponds to the connection types (usb_pin_connection_t) from pin1 to pin2, second nibble from pin2 to pin1
|
||||
* @note setting both levels (high, low) in both directions (pin1 to pin2 and pin2 to pin1) are tested, except for ground pins
|
||||
*/
|
||||
uint8_t usb_cables_check_pins(const struct usb_pin_t* pin1, const struct usb_pin_t* pin2);
|
||||
/** check connector for connections between pins of this connector
|
||||
* @param[in] connector connector to check
|
||||
* @param[out] connected which of the pins are connected (NULL to just print the pins)
|
||||
|
|
Loading…
Reference in New Issue