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 */
|
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) */
|
/** activity timeout before switching off (in seconds) */
|
||||||
#define SHUTDOWN_TIMEOUT 60
|
#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)
|
size_t putc(char c)
|
||||||
{
|
{
|
||||||
|
if (disable_print) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
size_t length = 0; // number of characters printed
|
size_t length = 0; // number of characters printed
|
||||||
static char last_c = 0; // to remember on which character we last sent
|
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
|
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
|
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
|
/** display available commands
|
||||||
* @param[in] argument no argument required
|
* @param[in] argument no argument required
|
||||||
*/
|
*/
|
||||||
|
@ -158,67 +511,52 @@ static void command_cables(void* argument)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** find out which USB cable is connected
|
/** 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)
|
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");
|
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
|
struct cable_t cable; // to store the cable finding results
|
||||||
uint16_t connections_nb = 0;
|
memset(&cable, 0, sizeof(struct cable_t)); // initialize cable structure
|
||||||
uint8_t (*connections)[2] = NULL;
|
cable_clear(&cable); // initialize rest of cable structure
|
||||||
connections = (uint8_t (*)[2])usb_cables_test_connections(usb_connectors, LENGTH(usb_connectors), false, true, &connections_nb);
|
|
||||||
if (NULL == connections) {
|
// find if cable is connected
|
||||||
if (connections_nb) {
|
cable_detect(&cable);
|
||||||
|
if (NULL == cable.connections) {
|
||||||
|
if (cable.connections_nb) {
|
||||||
printf("no memory available\n");
|
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 {
|
} else {
|
||||||
printf("no ground connections between connectors found\n");
|
if (!print_lcd) {
|
||||||
}
|
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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
goto end;
|
||||||
if (connections) {
|
|
||||||
free(connections);
|
|
||||||
connections = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%u connectors connected:\n", connectors_nb);
|
// find connected connectors
|
||||||
for (uint8_t i = 0; i < LENGTH(connected); i++) {
|
cable_connectors(&cable);
|
||||||
if (connected[i]) {
|
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);
|
printf("- %s", usb_connectors[i]->name);
|
||||||
if (usb_connectors[i]->variant) {
|
if (usb_connectors[i]->variant) {
|
||||||
printf(" (%s)", 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
|
// find cable with matching connector set
|
||||||
uint8_t matches = 0; // number of cables matching the connector set
|
cable_cables(&cable);
|
||||||
bool cable_connectors[LENGTH(usb_cables)]; // which cable matches the connector set
|
if (0 == cable.cables_nb) {
|
||||||
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) {
|
|
||||||
printf("found no cable with matching connector set\n");
|
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);
|
printf("found %u cable(s) with matching connectors:\n", cable.cables_nb);
|
||||||
for (uint8_t cable = 0; cable < LENGTH(usb_cables); cable++) {
|
for (uint8_t cable_i = 0; cable_i < LENGTH(cable.cables) && cable_i < LENGTH(usb_cables); cable_i++) {
|
||||||
if (!cable_connectors[cable]) { // skip if the cable connectors do not match
|
if (!cable.cables[cable_i]) { // skip if the cable connectors do not match
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
printf("- %02u %s\n", cable, usb_cables[cable].name);
|
printf("- %02u %s\n", cable_i, usb_cables[cable_i].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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate score for cables
|
// calculate score for cables
|
||||||
printf("cable scores (0 = perfect match):\n");
|
cable_issues_nb(&cable);
|
||||||
uint8_t cable_score = 0xff; // best cable score
|
if (!print_lcd) {
|
||||||
uint8_t cable_best = 0xff; // best cable index
|
printf("cable connection issue(s):\n");
|
||||||
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 < LENGTH(cable.cables) && cable_i < LENGTH(cable.unconnected_nb) && cable_i < LENGTH(cable.unspecified_nb); cable_i++) {
|
||||||
for (uint8_t cable_i = 0; cable_i < LENGTH(usb_cables); cable_i++) {
|
if (!cable.cables[cable_i]) { // skip if the cable connectors do not match
|
||||||
if (!cable_connectors[cable_i]) { // skip if the cable connectors do not match
|
continue;
|
||||||
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++;
|
|
||||||
}
|
}
|
||||||
|
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
|
// print result to LCD
|
||||||
lcd_hd44780_clear_display();
|
if (print_lcd) {
|
||||||
lcd_hd44780_display_control(true, false, false);
|
lcd_hd44780_clear_display();
|
||||||
if (cable_best < LENGTH(usb_cables)) {
|
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* cable = &usb_cables[cable_best];
|
const struct usb_cable_t* usb_cable = &usb_cables[cable.cable_best];
|
||||||
lcd_hd44780_write_line(false, cable->name, strlen(cable->name));
|
lcd_hd44780_write_line(false, usb_cable->name, strlen(usb_cable->name));
|
||||||
if (0 == cable_score) {
|
uint16_t issues = cable.unconnected_nb[cable.cable_best] + cable.unspecified_nb[cable.cable_best];
|
||||||
lcd_hd44780_write_line(true, "perfect match", 13);
|
if (0 == issues) {
|
||||||
} else {
|
lcd_hd44780_write_line(true, "perfect match", 13);
|
||||||
char score_str[17];
|
} else {
|
||||||
uint8_t str_len = snprintf(score_str, LENGTH(score_str), "issues: %u", cable_score);
|
char score_str[17];
|
||||||
if (str_len) {
|
uint8_t str_len = snprintf(score_str, LENGTH(score_str), "issues: %u", issues);
|
||||||
lcd_hd44780_write_line(true, score_str, str_len);
|
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 {
|
goto end;
|
||||||
lcd_hd44780_write_line(false, "no matching", 11);
|
|
||||||
lcd_hd44780_write_line(true, "cable found", 11);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
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
|
/** set or show pin value
|
||||||
|
@ -772,8 +1030,8 @@ static const struct menu_command_t menu_commands[] = {
|
||||||
.shortcut = 'f',
|
.shortcut = 'f',
|
||||||
.name = "find",
|
.name = "find",
|
||||||
.command_description = "find cable",
|
.command_description = "find cable",
|
||||||
.argument = MENU_ARGUMENT_NONE,
|
.argument = MENU_ARGUMENT_STRING,
|
||||||
.argument_description = NULL,
|
.argument_description = "[lcd]",
|
||||||
.command_handler = &command_find,
|
.command_handler = &command_find,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1022,12 +1280,14 @@ void main(void)
|
||||||
time_start = rtc_get_counter_val(); // get start time from internal RTC
|
time_start = rtc_get_counter_val(); // get start time from internal RTC
|
||||||
|
|
||||||
// setup LCD display
|
// setup LCD display
|
||||||
led_on(); // this actually power the I²C backpack and display
|
lcd_hd44780_i2c_addr = 0x3f; // set LCD backpack I²C slave address
|
||||||
lcd_hd44780_i2c_addr = 0x3f;
|
const char* lcd_default_line1 = "USB cable tester"; // default LCD text, when no cable is connected
|
||||||
if (lcd_hd44780_setup(true, false)) {
|
const char* lcd_default_line2 = "plug in cable"; // default LCD text, when no cable is connected
|
||||||
lcd_hd44780_display_control(true, false, true);
|
if (lcd_hd44780_setup(true, false)) { // setup LCD communication
|
||||||
lcd_hd44780_write_line(false, "USB cable tester", 16);
|
lcd_hd44780_display_control(true, false, false); // display on, cursor off, blink off
|
||||||
lcd_hd44780_write_line(true, "testing ...", 11);
|
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 {
|
} else {
|
||||||
printf("could not start LCD\n");
|
printf("could not start LCD\n");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue