From b4bf18c3167354c09a6ce75dea8d01727cf1969b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Sat, 21 Dec 2019 15:40:13 +0100 Subject: [PATCH] application: split find into individual functions --- application.c | 726 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 493 insertions(+), 233 deletions(-) diff --git a/application.c b/application.c index 5747657..5051d0f 100644 --- a/application.c +++ b/application.c @@ -69,11 +69,32 @@ static time_t time_start = 0; volatile bool rtc_internal_tick_flag = false; /**< flag set when internal RTC ticked */ /** @} */ +/** to disable the console print */ +bool disable_print = false; + /** activity timeout before switching off (in seconds) */ #define SHUTDOWN_TIMEOUT 60 +/** the current cable state */ +struct cable_t { + uint16_t connections_nb; // number of connections the cable has + uint8_t (*connections)[2]; // the cable connections (pin pairs) + uint8_t connectors_nb; // number of connectors the cable has + bool connectors[LENGTH(usb_connectors)]; // which connectors the cable connects + uint8_t cables_nb; // number of cable definitions the connectors set match to + bool cables[LENGTH(usb_cables)]; // cable definitions the connectors set match to + uint16_t unconnected_nb[LENGTH(usb_cables)]; // number of unconnected pairs which should be connected according to cable specification + uint16_t unspecified_nb[LENGTH(usb_cables)]; // number of connected pairs which are not specified by cable + uint8_t cable_best; // best matching cable index (e.g. with lowest score) + uint8_t (*unconnected)[2]; // unconnected pairs which should be connected according to best cable specification + uint8_t (*unspecified)[2]; // connected pairs which are not specified by best cable +}; + size_t putc(char c) { + if (disable_print) { + return 0; + } size_t length = 0; // number of characters printed static char last_c = 0; // to remember on which character we last sent if ('\n' == c) { // send carriage return (CR) + line feed (LF) newline for each LF @@ -94,6 +115,338 @@ static void usb_pins_float(void) usb_cables_connectors_float(usb_connectors, LENGTH(usb_connectors)); // put every pin of every connector in floating mode } +/** clear the cable information + * @param[out] cable structure to be cleared + */ +static void cable_clear(struct cable_t* cable) +{ + // check input arguments + if (NULL == cable) { + return; + } + + // initialize structure + cable->connections_nb = 0; + if (cable->connections) { + free(cable->connections); + cable->connections = NULL; + } + cable->connectors_nb = 0; + for (uint8_t i = 0; i < LENGTH(cable->connectors); i++) { + cable->connectors[i] = false; + } + cable->cables_nb = 0; + for (uint8_t i = 0; i < LENGTH(cable->cables); i++) { + cable->cables[i] = false; + } + for (uint8_t i = 0; i < LENGTH(cable->unconnected_nb); i++) { + cable->unconnected_nb[i] = 0; + } + for (uint8_t i = 0; i < LENGTH(cable->unspecified_nb); i++) { + cable->unspecified_nb[i] = 0; + } + cable->cable_best = 0xff; + if (cable->unconnected) { + free(cable->unconnected); + cable->unconnected = NULL; + } + if (cable->unspecified) { + free(cable->unspecified); + cable->unspecified = NULL; + } +} + +/** detect cable presence by testing inter-connector ground connections + * @param[out] cable what cable it found + * @note only sets the ground connections and connections_nb + */ +static void cable_detect(struct cable_t* cable) +{ + // check input arguments + if (NULL == cable) { + return; + } + + usb_pins_float(); // start with all pins in safe floating state + if (cable->connections) { + free(cable->connections); + } + cable->connections = (uint8_t (*)[2])usb_cables_test_connections(usb_connectors, LENGTH(usb_connectors), false, true, &cable->connections_nb); // figure out which connectors are connector by testing ground pin connections +} + +/** find which connectors the connections belong to + * @param[io] cable cable for which to find which connectors it connects + * @note only updates connectors_nb and connectors based on connections + */ +static void cable_connectors(struct cable_t* cable) +{ + // check input arguments + if (NULL == cable) { + return; + } + + // initialize relevant structure variables + cable->connectors_nb = 0; + for (uint8_t i = 0; i < LENGTH(cable->connectors); i++) { + cable->connectors[i] = false; + } + + // ensure connections are available + if (NULL == cable->connections || 0 == cable->connections_nb) { + return; + } + + // find which connectors the connections belong to + for (uint16_t connection = 0; connection < cable->connections_nb; connection++) { + const struct usb_connector_t* connector_from = usb_cables_get_connector(cable->connections[connection][0]); + const struct usb_connector_t* connector_to = usb_cables_get_connector(cable->connections[connection][1]); + if (NULL == connector_from || NULL == connector_to) { + continue; + } + for (uint8_t i = 0; i < LENGTH(cable->connectors) && i < LENGTH(usb_connectors); i++) { + if (usb_connectors[i] == connector_from || usb_connectors[i] == connector_to) { + cable->connectors[i] = true; + } + } + } + + // calculate the numbers of connectors connected + for (uint8_t i = 0; i < LENGTH(cable->connectors) && i < LENGTH(usb_connectors); i++) { + if (cable->connectors[i]) { + cable->connectors_nb++; + } + } +} + +/** find which cables match the connector set + * @param[io] cable cable for which to find matching cable definitions + * @note only updates cables_nb and cables based on connectors + */ +static void cable_cables(struct cable_t* cable) +{ + // check input arguments + if (NULL == cable) { + return; + } + + // initialize relevant structure variables + cable->cables_nb = 0; + for (uint8_t i = 0; i < LENGTH(cable->cables); i++) { + cable->cables[i] = false; + } + + // ensure connections are available + if (0 == cable->connectors_nb) { + return; + } + + // find cable with matching connector set + for (uint8_t cable_i = 0; cable_i < LENGTH(cable->cables) && cable_i < LENGTH(usb_cables); cable_i++) { + cable->cables[cable_i] = false; // start with not matching, and test if it matches + // ensure we have the same number of connections as the cable + if (usb_cables[cable_i].connectors_nb != cable->connectors_nb) { + continue; + } + // ensure all the connectors we have are also in the cable + bool match = true; + for (uint8_t i = 0; i < LENGTH(usb_connectors) && match; i++) { + if (!cable->connectors[i]) { + continue; + } + bool found = false; + for (uint8_t j = 0; j < usb_cables[cable_i].connectors_nb && !found; j++) { + if (usb_connectors[i] == usb_cables[cable_i].connectors[j]) { + found = true; + } + } + if (!found) { + match = false; + } + } + // ensure we also have all the connectors which are in the cable + for (uint8_t i = 0; i < usb_cables[cable_i].connectors_nb && match; i++) { + bool found = false; + for (uint8_t j = 0; j < LENGTH(usb_connectors) && !found; j++) { + if (!cable->connectors[j]) { + continue; + } + if (usb_connectors[j] == usb_cables[cable_i].connectors[i]) { + found = true; + } + } + if (!found) { + match = false; + } + } + cable->cables[cable_i] = match; + if (match) { + cable->cables_nb++; + } + } +} + +/** calculate number of issues for matching cables + * @param[io] cable cable for which to find the number of issues + * @note set unconnected_nb, unspecified_nb, and cable_best based on cables + */ +static void cable_issues_nb(struct cable_t* cable) +{ + // check input arguments + if (NULL == cable) { + return; + } + + // initialize relevant structure variables + for (uint8_t i = 0; i < LENGTH(cable->unconnected_nb); i++) { + cable->unconnected_nb[i] = 0; + } + for (uint8_t i = 0; i < LENGTH(cable->unspecified_nb); i++) { + cable->unspecified_nb[i] = 0; + } + cable->cable_best = 0xff; + + // ensure connections are available + if (0 == cable->cables_nb) { + return; + } + + // get the connectors + const struct usb_connector_t* connectors[LENGTH(usb_connectors)]; + uint8_t connectors_nb = 0; + for (uint8_t i = 0; i < LENGTH(usb_connectors) && i < LENGTH(connectors) && i < LENGTH(cable->connectors) && connectors_nb < cable->connectors_nb; i++) { + if (cable->connectors[i]) { + connectors[connectors_nb++] = usb_connectors[i]; + } + } + + // get all connections once + if (cable->connections) { + free(cable->connections); + cable->connections = NULL; + } + cable->connections = (uint8_t (*)[2])usb_cables_test_connections(connectors, connectors_nb, true, false, &cable->connections_nb); + if (NULL == cable->connections || 0 == cable->connections_nb) { + return; + } + + // calculate score for cables + uint16_t best_score = UINT16_MAX; // best cable score + for (uint8_t cable_i = 0; cable_i < LENGTH(usb_cables) && cable_i < LENGTH(cable->cables) && cable_i < LENGTH(cable->unconnected_nb) && cable_i < LENGTH(cable->unspecified_nb); cable_i++) { + if (!cable->cables[cable_i]) { // skip if the cable connectors do not match + continue; + } + const struct usb_cable_t* usb_cable = &usb_cables[cable_i]; + cable->unconnected_nb[cable_i] = usb_cable->pin_pairs_nb; + cable->unspecified_nb[cable_i] = 0; + for (uint16_t i = 0; i < cable->connections_nb; i++) { + bool match = false; + for (uint8_t j = 0; j < usb_cable->pin_pairs_nb; j++) { + if (cable->connections[i][0] == usb_cable->pin_pairs[j][0] && cable->connections[i][1] == usb_cable->pin_pairs[j][1]) { + match = true; + } else if (cable->connections[i][0] == usb_cable->pin_pairs[j][1] && cable->connections[i][1] == usb_cable->pin_pairs[j][0]) { + match = true; + } + } + if (match) { + cable->unconnected_nb[cable_i]--; + } else { + cable->unspecified_nb[cable_i]++; + } + } + uint16_t score = cable->unconnected_nb[cable_i] + cable->unspecified_nb[cable_i]; + if (score < best_score) { + best_score = score; + cable->cable_best = cable_i; + } + } +} + +/** list issues for best matching cable + * @param[io] cable cable for which to calculate the score + * @note set unconnected and unspecified based on cable_best + */ +static void cable_issues(struct cable_t* cable) +{ + // check input arguments + if (NULL == cable) { + return; + } + if (cable->cable_best >= LENGTH(usb_cables) || cable->cable_best >= LENGTH(cable->cables) || !cable->cables[cable->cable_best] || cable->cable_best >= LENGTH(cable->unconnected_nb) || cable->cable_best >= LENGTH(cable->unspecified_nb)) { + return; + } + + // initialize relevant variables + if (cable->unconnected) { + free(cable->unconnected); + cable->unconnected = NULL; + } + cable->unconnected_nb[cable->cable_best] = 0; + if (cable->unspecified) { + free(cable->unspecified); + cable->unspecified = NULL; + } + cable->unspecified_nb[cable->cable_best] = 0; + + // find if cable pairs are actual connection + const struct usb_cable_t* usb_cable = &usb_cables[cable->cable_best]; + for (uint16_t i = 0; i < usb_cable->pin_pairs_nb; i++) { + bool match = false; + for (uint8_t j = 0; j < cable->connections_nb; j++) { + if (cable->connections[j][0] == usb_cable->pin_pairs[i][0] && cable->connections[j][1] == usb_cable->pin_pairs[i][1]) { + match = true; + } else if (cable->connections[j][0] == usb_cable->pin_pairs[i][1] && cable->connections[j][1] == usb_cable->pin_pairs[i][0]) { + match = true; + } + } + if (!match) { + cable->unconnected_nb[cable->cable_best]++; + uint8_t (*new_connections)[2] = realloc(cable->unconnected, cable->unconnected_nb[cable->cable_best] * sizeof(uint8_t[2])); // no integer overflow is possible because of the max number of connections + if (NULL == new_connections) { // allocation failed + if (cable->unconnected) { + free(cable->unconnected); + } + cable->unconnected = NULL; + cable->unconnected_nb[cable->cable_best] = 0; + return; // fail-safe return (without indicating error) + } + cable->unconnected = new_connections; + cable->unconnected[cable->unconnected_nb[cable->cable_best] - 1][0] = usb_cable->pin_pairs[i][0]; + cable->unconnected[cable->unconnected_nb[cable->cable_best] - 1][1] = usb_cable->pin_pairs[i][1]; + } + } + + // find if connection is defined in cable + for (uint16_t i = 0; i < cable->connections_nb; i++) { + bool match = false; + for (uint8_t j = 0; j < usb_cable->pin_pairs_nb; j++) { + if (cable->connections[i][0] == usb_cable->pin_pairs[j][0] && cable->connections[i][1] == usb_cable->pin_pairs[j][1]) { + match = true; + } else if (cable->connections[i][0] == usb_cable->pin_pairs[j][1] && cable->connections[i][1] == usb_cable->pin_pairs[j][0]) { + match = true; + } + } + if (!match) { + cable->unspecified_nb[cable->cable_best]++; + uint8_t (*new_connections)[2] = realloc(cable->unspecified, cable->unspecified_nb[cable->cable_best] * sizeof(uint8_t[2])); // no integer overflow is possible because of the max number of connections + if (NULL == new_connections) { // allocation failed + if (cable->unspecified) { + free(cable->unspecified); + } + cable->unspecified = NULL; + cable->unspecified_nb[cable->cable_best] = 0; + return; // fail-safe return (without indicating error) + } + cable->unspecified = new_connections; + cable->unspecified[cable->unspecified_nb[cable->cable_best] - 1][0] = cable->connections[i][0]; + cable->unspecified[cable->unspecified_nb[cable->cable_best] - 1][1] = cable->connections[i][1]; + } + } +} + +// =================== +// = action commands = +// =================== + /** display available commands * @param[in] argument no argument required */ @@ -158,67 +511,52 @@ static void command_cables(void* argument) } /** find out which USB cable is connected - * @param[in] argument no argument required + * @param[in] argument NULL to print on console, "lcd" to print on LCD */ static void command_find(void* argument) { - (void)argument; // we won't use the argument + char* arg = (char*)argument; // we won't use the argument + bool print_lcd = false; + + if (arg) { + if (0 == strcmp(arg, "lcd")) { + print_lcd = true; + disable_print = true; + } else { + printf("unknown argument %s\n", arg); + return; + } + } printf("= finding cable =\n"); - usb_pins_float(); // start with all pins in safe floating state - // figure out which connectors are connector by testing ground pin connections - uint16_t connections_nb = 0; - uint8_t (*connections)[2] = NULL; - connections = (uint8_t (*)[2])usb_cables_test_connections(usb_connectors, LENGTH(usb_connectors), false, true, &connections_nb); - if (NULL == connections) { - if (connections_nb) { + struct cable_t cable; // to store the cable finding results + memset(&cable, 0, sizeof(struct cable_t)); // initialize cable structure + cable_clear(&cable); // initialize rest of cable structure + + // find if cable is connected + cable_detect(&cable); + if (NULL == cable.connections) { + if (cable.connections_nb) { printf("no memory available\n"); + if (print_lcd) { + lcd_hd44780_clear_display(); + char lcd_str[] = "testing error"; + lcd_hd44780_write_line(false, lcd_str, strlen(lcd_str)); + } } else { - printf("no ground connections between connectors found\n"); - } - return; - } - - bool connected[LENGTH(usb_connectors)]; - for (uint8_t i = 0; i < LENGTH(connected); i++) { - connected[i] = false; - } - const struct usb_connector_t* connectors[LENGTH(usb_connectors)]; - uint8_t connectors_nb = 0; - for (uint8_t i = 0; i < LENGTH(connectors); i++) { - connectors[i] = NULL; - } - for (uint16_t connection = 0; connection < connections_nb; connection++) { - const struct usb_connector_t* connector_from = usb_cables_get_connector(connections[connection][0]); - const struct usb_connector_t* connector_to = usb_cables_get_connector(connections[connection][1]); - if (NULL == connector_from || NULL == connector_to) { - printf("no connector for a pin pair\n"); - continue; - } - for (uint8_t i = 0; i < LENGTH(connected) && i < LENGTH(usb_connectors); i++) { - if (usb_connectors[i] == connector_from) { - if (!connected[i]) { - connected[i] = true; - connectors[connectors_nb++] = usb_connectors[i]; - } - } - if (usb_connectors[i] == connector_to) { - if (!connected[i]) { - connected[i] = true; - connectors[connectors_nb++] = usb_connectors[i]; - } + if (!print_lcd) { + printf("no ground connections between connectors found\n"); } } - } - if (connections) { - free(connections); - connections = NULL; + goto end; } - printf("%u connectors connected:\n", connectors_nb); - for (uint8_t i = 0; i < LENGTH(connected); i++) { - if (connected[i]) { + // find connected connectors + cable_connectors(&cable); + printf("%u connectors connected:\n", cable.connectors_nb); + for (uint8_t i = 0; i < LENGTH(cable.connectors) && i < LENGTH(usb_connectors); i++) { + if (cable.connectors[i]) { printf("- %s", usb_connectors[i]->name); if (usb_connectors[i]->variant) { printf(" (%s)", usb_connectors[i]->variant); @@ -228,199 +566,119 @@ static void command_find(void* argument) } // find cable with matching connector set - uint8_t matches = 0; // number of cables matching the connector set - bool cable_connectors[LENGTH(usb_cables)]; // which cable matches the connector set - for (uint8_t cable = 0; cable < LENGTH(usb_cables); cable++) { - cable_connectors[cable] = false; // start with not matching, and test if it matches - // ensure we have the same number of connections as the cable - if (usb_cables[cable].connectors_nb != connectors_nb) { - continue; - } - // ensure all the connectors we have are also in the cable - bool match = true; - for (uint8_t i = 0; i < LENGTH(usb_connectors) && match; i++) { - if (!connected[i]) { - continue; - } - bool found = false; - for (uint8_t j = 0; j < usb_cables[cable].connectors_nb; j++) { - if (usb_connectors[i] == usb_cables[cable].connectors[j]) { - found = true; - } - } - if (!found) { - match = false; - } - } - // ensure we also have all the connectors which are in the cable - for (uint8_t i = 0; i < usb_cables[cable].connectors_nb && match; i++) { - bool found = false; - for (uint8_t j = 0; j < LENGTH(usb_connectors); j++) { - if (!connected[j]) { - continue; - } - if (usb_connectors[j] == usb_cables[cable].connectors[i]) { - found = true; - } - } - if (!found) { - match = false; - } - } - cable_connectors[cable] = match; - if (match) { - matches++; - } - } - - // test how well the pins of the cables with matching connectors match - if (0 == matches) { + cable_cables(&cable); + if (0 == cable.cables_nb) { printf("found no cable with matching connector set\n"); - return; + if (print_lcd) { + lcd_hd44780_clear_display(); + char lcd_str[] = "unknown cable"; + lcd_hd44780_write_line(false, lcd_str, strlen(lcd_str)); + } + goto end; } - printf("found %u cable(s) with matching connectors:\n", matches); - for (uint8_t cable = 0; cable < LENGTH(usb_cables); cable++) { - if (!cable_connectors[cable]) { // skip if the cable connectors do not match + printf("found %u cable(s) with matching connectors:\n", cable.cables_nb); + for (uint8_t cable_i = 0; cable_i < LENGTH(cable.cables) && cable_i < LENGTH(usb_cables); cable_i++) { + if (!cable.cables[cable_i]) { // skip if the cable connectors do not match continue; } - printf("- %02u %s\n", cable, usb_cables[cable].name); - } - - // get all connections once - connections = (uint8_t (*)[2])usb_cables_test_connections(connectors, connectors_nb, true, false, &connections_nb); - if (NULL == connections) { - if (connections_nb) { - printf("no memory available\n"); - } else { - printf("no connections\n"); - } - return; + printf("- %02u %s\n", cable_i, usb_cables[cable_i].name); } // calculate score for cables - printf("cable scores (0 = perfect match):\n"); - uint8_t cable_score = 0xff; // best cable score - uint8_t cable_best = 0xff; // best cable index - uint8_t cable_scores[LENGTH(usb_cables)]; // how close the cable matches (0 = perfect match) - for (uint8_t cable_i = 0; cable_i < LENGTH(usb_cables); cable_i++) { - if (!cable_connectors[cable_i]) { // skip if the cable connectors do not match - continue; - } - const struct usb_cable_t* cable = &usb_cables[cable_i]; - uint8_t defined = 0, undefined = 0; // count the (un)specified connections - for (uint16_t i = 0; i < connections_nb; i++) { - bool match = false; - for (uint8_t j = 0; j < cable->pin_pairs_nb; j++) { - if (connections[i][0] == cable->pin_pairs[j][0] && connections[i][1] == cable->pin_pairs[j][1]) { - match = true; - } else if (connections[i][0] == cable->pin_pairs[j][1] && connections[i][1] == cable->pin_pairs[j][0]) { - match = true; - } - } - if (match) { - defined++; - } else { - undefined++; + cable_issues_nb(&cable); + if (!print_lcd) { + printf("cable connection issue(s):\n"); + for (uint8_t cable_i = 0; cable_i < LENGTH(usb_cables) && cable_i < LENGTH(cable.cables) && cable_i < LENGTH(cable.unconnected_nb) && cable_i < LENGTH(cable.unspecified_nb); cable_i++) { + if (!cable.cables[cable_i]) { // skip if the cable connectors do not match + continue; } + uint16_t issues = cable.unconnected_nb[cable_i] + cable.unspecified_nb[cable_i]; + printf("- %02u %s: %u (unconnected=%u/%u, undefined=%u)\n", cable_i, usb_cables[cable_i].name, issues, cable.unconnected_nb[cable_i], usb_cables[cable_i].pin_pairs_nb, cable.unspecified_nb[cable_i]); } - cable_scores[cable_i] = cable->pin_pairs_nb - defined + undefined; - if (cable_scores[cable_i] < cable_score) { - cable_score = cable_scores[cable_i]; - cable_best = cable_i; - } - printf("- %02u %s: %u (defined=%u/%u, undefined=%u)\n", cable_i, usb_cables[cable_i].name, cable_scores[cable_i], defined, cable->pin_pairs_nb, undefined); - } - - if (cable_best < LENGTH(usb_cables)) { - const struct usb_cable_t* cable = &usb_cables[cable_best]; - if (0 == cable_score) { - printf("perfect matching cable: %s\n", cable->name); - } else { - printf("best matching cable: %s\n", cable->name); - // find if cable pairs are actual connection - for (uint16_t i = 0; i < cable->pin_pairs_nb; i++) { - bool match = false; - for (uint8_t j = 0; j < connections_nb; j++) { - if (connections[j][0] == cable->pin_pairs[i][0] && connections[j][1] == cable->pin_pairs[i][1]) { - match = true; - } else if (connections[j][0] == cable->pin_pairs[i][1] && connections[j][1] == cable->pin_pairs[i][0]) { - match = true; - } - } - if (!match) { - const struct usb_connector_t* connector_from = usb_cables_get_connector(cable->pin_pairs[i][0]); - const struct usb_connector_t* connector_to = usb_cables_get_connector(cable->pin_pairs[i][1]); - if (NULL == connector_from || NULL == connector_to) { - continue; - } - printf("not connected: %s ", connector_from->name); - if (connector_from->variant) { - printf("(%s) ", connector_from->variant); - } - printf("%s to %s ", usb_pins[cable->pin_pairs[i][0]].name, connector_to->name); - if (connector_to->variant) { - printf("(%s) ", connector_from->variant); - } - printf("%s\n", usb_pins[cable->pin_pairs[i][1]].name); - } - } - // find if connection is defined in cable - for (uint16_t i = 0; i < connections_nb; i++) { - bool match = false; - for (uint8_t j = 0; j < cable->pin_pairs_nb; j++) { - if (connections[i][0] == cable->pin_pairs[j][0] && connections[i][1] == cable->pin_pairs[j][1]) { - match = true; - } else if (connections[i][0] == cable->pin_pairs[j][1] && connections[i][1] == cable->pin_pairs[j][0]) { - match = true; - } - } - if (!match) { - const struct usb_connector_t* connector_from = usb_cables_get_connector(connections[i][0]); - const struct usb_connector_t* connector_to = usb_cables_get_connector(connections[i][1]); - if (NULL == connector_from || NULL == connector_to) { - continue; - } - printf("undefined connection: %s ", connector_from->name); - if (connector_from->variant) { - printf("(%s) ", connector_from->variant); - } - printf("%s to %s ", usb_pins[connections[i][0]].name, connector_to->name); - if (connector_to->variant) { - printf("(%s) ", connector_from->variant); - } - printf("%s\n", usb_pins[connections[i][1]].name); - } - } - } - } else { - printf("no matching cable found\n"); - } - if (connections) { - free(connections); - connections = NULL; } // print result to LCD - lcd_hd44780_clear_display(); - lcd_hd44780_display_control(true, false, false); - if (cable_best < LENGTH(usb_cables)) { - const struct usb_cable_t* cable = &usb_cables[cable_best]; - lcd_hd44780_write_line(false, cable->name, strlen(cable->name)); - if (0 == cable_score) { - lcd_hd44780_write_line(true, "perfect match", 13); - } else { - char score_str[17]; - uint8_t str_len = snprintf(score_str, LENGTH(score_str), "issues: %u", cable_score); - if (str_len) { - lcd_hd44780_write_line(true, score_str, str_len); + if (print_lcd) { + lcd_hd44780_clear_display(); + if (cable.cable_best < LENGTH(usb_cables) && cable.cable_best < LENGTH(cable.unconnected_nb) && cable.cable_best < LENGTH(cable.unconnected_nb)) { + const struct usb_cable_t* usb_cable = &usb_cables[cable.cable_best]; + lcd_hd44780_write_line(false, usb_cable->name, strlen(usb_cable->name)); + uint16_t issues = cable.unconnected_nb[cable.cable_best] + cable.unspecified_nb[cable.cable_best]; + if (0 == issues) { + lcd_hd44780_write_line(true, "perfect match", 13); + } else { + char score_str[17]; + uint8_t str_len = snprintf(score_str, LENGTH(score_str), "issues: %u", issues); + if (str_len) { + lcd_hd44780_write_line(true, score_str, str_len); + } } + } else { + lcd_hd44780_write_line(false, "no matching", 11); + lcd_hd44780_write_line(true, "cable found", 11); } - } else { - lcd_hd44780_write_line(false, "no matching", 11); - lcd_hd44780_write_line(true, "cable found", 11); + goto end; } + // print connection details + cable_issues(&cable); + if (cable.cable_best < LENGTH(usb_cables) && cable.cable_best < LENGTH(cable.unconnected_nb) && cable.cable_best < LENGTH(cable.unconnected_nb) && cable.cables[cable.cable_best]) { + // there is a matching cable + } else { + printf("no matching cable found\n"); + goto end; + } + const struct usb_cable_t* usb_cable = &usb_cables[cable.cable_best]; + const uint16_t issues = cable.unconnected_nb[cable.cable_best] + cable.unspecified_nb[cable.cable_best]; + if (0 == issues) { + printf("perfect matching cable: %s\n", usb_cable->name); + goto end; + } + printf("closes matching cable: %s\n", usb_cable->name); + printf("%u connection issue(s) (%u unconnected, %u unspecified)\n", issues, cable.unconnected_nb[cable.cable_best], cable.unspecified_nb[cable.cable_best]); + if (cable.unconnected_nb[cable.cable_best] > 0) { + printf("unconnected pins:\n"); + for (uint16_t i = 0; i < cable.unconnected_nb[cable.cable_best]; i++) { + const struct usb_connector_t* connector_from = usb_cables_get_connector(cable.unconnected[i][0]); + const struct usb_connector_t* connector_to = usb_cables_get_connector(cable.unconnected[i][1]); + if (NULL == connector_from || NULL == connector_to) { + continue; + } + printf("- %s ", connector_from->name); + if (connector_from->variant) { + printf("(%s) ", connector_from->variant); + } + printf("%s to %s ", usb_pins[cable.unconnected[i][0]].name, connector_to->name); + if (connector_to->variant) { + printf("(%s) ", connector_from->variant); + } + printf("%s\n", usb_pins[cable.unconnected[i][1]].name); + } + } + if (cable.unspecified_nb[cable.cable_best] > 0) { + printf("unspecified pins connections:\n"); + for (uint16_t i = 0; i < cable.unspecified_nb[cable.cable_best]; i++) { + const struct usb_connector_t* connector_from = usb_cables_get_connector(cable.unspecified[i][0]); + const struct usb_connector_t* connector_to = usb_cables_get_connector(cable.unspecified[i][1]); + if (NULL == connector_from || NULL == connector_to) { + continue; + } + printf("- %s ", connector_from->name); + if (connector_from->variant) { + printf("(%s) ", connector_from->variant); + } + printf("%s to %s ", usb_pins[cable.unspecified[i][0]].name, connector_to->name); + if (connector_to->variant) { + printf("(%s) ", connector_from->variant); + } + printf("%s\n", usb_pins[cable.unspecified[i][1]].name); + } + } + +end: usb_pins_float(); // put all pins back in safe floating state + cable_clear(&cable); // free allocated memory + disable_print = false; // enable serial print again } /** set or show pin value @@ -772,8 +1030,8 @@ static const struct menu_command_t menu_commands[] = { .shortcut = 'f', .name = "find", .command_description = "find cable", - .argument = MENU_ARGUMENT_NONE, - .argument_description = NULL, + .argument = MENU_ARGUMENT_STRING, + .argument_description = "[lcd]", .command_handler = &command_find, }, { @@ -1022,12 +1280,14 @@ void main(void) time_start = rtc_get_counter_val(); // get start time from internal RTC // setup LCD display - led_on(); // this actually power the I²C backpack and display - lcd_hd44780_i2c_addr = 0x3f; - if (lcd_hd44780_setup(true, false)) { - lcd_hd44780_display_control(true, false, true); - lcd_hd44780_write_line(false, "USB cable tester", 16); - lcd_hd44780_write_line(true, "testing ...", 11); + lcd_hd44780_i2c_addr = 0x3f; // set LCD backpack I²C slave address + const char* lcd_default_line1 = "USB cable tester"; // default LCD text, when no cable is connected + const char* lcd_default_line2 = "plug in cable"; // default LCD text, when no cable is connected + if (lcd_hd44780_setup(true, false)) { // setup LCD communication + lcd_hd44780_display_control(true, false, false); // display on, cursor off, blink off + lcd_hd44780_clear_display(); // be sure the display is cleared + lcd_hd44780_write_line(false, lcd_default_line1, strlen(lcd_default_line1)); + lcd_hd44780_write_line(true, lcd_default_line2, strlen(lcd_default_line2)); } else { printf("could not start LCD\n"); }