application: split find into individual functions

This commit is contained in:
King Kévin 2019-12-21 15:40:13 +01:00
parent 1e808f66b2
commit b4bf18c316
1 changed files with 493 additions and 233 deletions

View File

@ -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");
}