application: split find into individual functions
This commit is contained in:
parent
1e808f66b2
commit
b4bf18c316
726
application.c
726
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");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue