application: rewrite find action and make faster

This commit is contained in:
King Kévin 2019-12-13 17:23:19 +01:00
parent 28024ae960
commit dd509c3d8f
1 changed files with 187 additions and 49 deletions

View File

@ -161,15 +161,59 @@ static void command_find(void* argument)
{
(void)argument; // we won't use the argument
printf("= cable finder =\n");
printf("= finding cable =\n");
usb_pins_float(); // start with all pins in safe floating state
// figure out which connectors are used
// 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) {
printf("no memory available\n");
} else {
printf("no ground connections between connectors found\n");
}
return;
}
bool connected[LENGTH(usb_connectors)];
//usb_cables_check_inter(usb_connectors, LENGTH(usb_connectors), connected);
usb_cables_check_ground(usb_connectors, LENGTH(usb_connectors), connected);
uint8_t connected_nb = 0;
printf("connectors:\n");
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 (connections) {
free(connections);
connections = NULL;
}
printf("%u connectors connected:\n", connectors_nb);
for (uint8_t i = 0; i < LENGTH(connected); i++) {
if (connected[i]) {
printf("- %s", usb_connectors[i]->name);
@ -177,7 +221,6 @@ static void command_find(void* argument)
printf(" (%s)", usb_connectors[i]->variant);
}
putc('\n');
connected_nb++;
}
}
@ -187,7 +230,7 @@ static void command_find(void* argument)
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 != connected_nb) {
if (usb_cables[cable].connectors_nb != connectors_nb) {
continue;
}
// ensure all the connectors we have are also in the cable
@ -228,55 +271,150 @@ static void command_find(void* argument)
}
// test how well the pins of the cables with matching connectors match
printf("found %u cable(s) with matching connectors%s\n", matches, matches > 0 ? ":" : "");
if (0 == matches) {
printf("found no cable with matching connector set\n");
return;
}
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
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;
}
matches = 0; // number of matching cables
uint8_t cable_score[LENGTH(usb_cables)]; // how close the cable matches (0 = perfect match)
for (uint8_t cable = 0; cable < LENGTH(usb_cables); cable++) {
cable_score[cable] = 0xff; // initialise with worst score
if (!cable_connectors[cable]) { // skip if the cable connectors do not match
// 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;
}
// match cable
uint8_t pair_defined, pair_undefined;
bool match = usb_cables_check_cable(&usb_cables[cable], &pair_defined, &pair_undefined, false);
printf("- %s: %s (defined=%u/%u, undefined=%u)\n", match ? "OK" : "KO", usb_cables[cable].name, pair_defined, usb_cables[cable].pin_pairs_nb, pair_undefined);
cable_score[cable] = usb_cables[cable].pin_pairs_nb - pair_defined + pair_undefined; // calculate score
if (match) {
matches++;
}
}
printf("%u perfect matching cable(s) found\n", matches);
// find best matching cable
uint8_t best_score = 0xff;
for (uint8_t cable = 0; cable < LENGTH(usb_cables); cable++) {
if (!cable_connectors[cable]) { // skip if the cable connectors do not match
continue;
}
if (cable_score[cable] < best_score) {
best_score = cable_score[cable];
}
}
printf("%smatching cable(s):\n", 0 == best_score ? "" : "closest ");
for (uint8_t cable = 0; cable < LENGTH(usb_cables); cable++) {
if (!cable_connectors[cable]) { // skip if the cable connectors do not match
continue;
}
if (cable_score[cable] == best_score) {
// print cable connections
printf("- %s\n", usb_cables[cable].name);
usb_cables_check_cable(&usb_cables[cable], NULL, NULL, true);
// test if there is a load
bool loaded = false;
for (uint8_t connector = 0; connector < usb_cables[cable].connectors_nb; connector++) {
loaded |= usb_cables_check_load(usb_cables[cable].connectors[connector]);
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++;
}
printf("there is %s load on the cable\n", loaded ? "a" : "no");
}
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);
}
}
} else {
lcd_hd44780_write_line(false, "no matching", 11);
lcd_hd44780_write_line(true, "cable found", 11);
}
usb_pins_float(); // put all pins back in safe floating state