application: add eMrker read out

This commit is contained in:
King Kévin 2020-03-01 23:22:49 +01:00
parent 0c5f5e8c2d
commit 9d7e4940e9
1 changed files with 188 additions and 12 deletions

View File

@ -50,6 +50,9 @@
#include "oled_text.h" // OLED utilities to display text
#include "usb_fusb302.h" // USB-C controller utilities
/* external library */
#include "usb_pd.h" // USB Power Delivery definitions
/** watchdog period in ms */
#define WATCHDOG_PERIOD 10000
@ -1235,6 +1238,94 @@ static void command_connections(void* argument)
}
}
/** print discovery identity response (e.g. eMarker information)
* param[in] packet FUSB302 packet containing VDM information
*/
static void print_emarker(uint8_t* packet)
{
const uint16_t header = (packet[2] << 8) + packet[1];
if (0 == PD_HEADER_CNT(header)) { // it's a control packet, not a data packet
return;
}
if (PD_DATA_VENDOR_DEF != PD_HEADER_TYPE(header)) { // not a VDM message
return;
}
// get objects
uint32_t objects[7]; // maximum message length
for (uint8_t i = 0; i < PD_HEADER_CNT(header); i++) {
objects[i] = (packet[i * 4 + 3 + 3] << 24) + (packet[i * 4 + 3 + 2] << 16) + (packet[i * 4 + 3 + 1] << 8) + (packet[i * 4 + 3 + 0] << 0);
}
puts("cable eMarker attributes:\n");
// decode some messages
const uint32_t vdm_header = objects[0];
if (vdm_header & VDO_SVDM_TYPE && VDO_CMDT(CMDT_RSP_ACK) == (vdm_header & VDO_CMDT_MASK) && CMD_DISCOVER_IDENT == (vdm_header & 0x1f)) { // we have a discover identity response
if (PD_HEADER_CNT(header) > 1) { // ID Header VDO (6.4.4.3.1.1)
//printf("- host %s enumerate\n", (objects[1] & (1 << 31)) ? "can" : "can't");
//printf("- device %s be enumerated\n", (objects[1] & (1 << 30)) ? "can" : "can't");
if (PD_HEADER_PROLE(header)) { // this is a plug
switch (PD_IDH_PTYPE(objects[1])) {
case 3:
puts("- cable: passive\n");
break;
case 4:
puts("- cable: active\n");
break;
default:
break;
}
}
printf("- VID: %04x\n", PD_IDH_VID(objects[1]));
}
if (PD_HEADER_CNT(header) > 2) { // Cert Stat VDO (6.4.4.3.1.2)
//printf("- cert stat: %08x\n", objects[2]);
}
if (PD_HEADER_CNT(header) > 3) { // Product VDO (6.4.4.3.1.3)
//printf("- product ID: %04x, bcdDevice: %04x\n", objects[3] >> 16, objects[3] & 0xffff);
}
if (PD_HEADER_CNT(header) > 3 && PD_HEADER_PROLE(header) && 3 == PD_IDH_PTYPE(objects[1])) { // Passive Cable VDO (6.4.4.3.1.4)
union cable_vdo cable;
memset(&cable, 0, sizeof(cable));
cable.raw_value = objects[4];
printf("- HW version: %u\n", cable.p_rev30.hw_version);
printf("- FW version: %u\n", cable.p_rev30.fw_version);
printf("- cable length: ~%um\n", ((cable.raw_value >> 13) & 0x7));
printf("- VCONN: %srequired\n", ((cable.raw_value >> 11) & 0x3) ? "" : "not ");
printf("- maximum VBUS voltage: %uV\n", ((cable.raw_value >> 9) & 0x3) * 10 + 20);
puts("- maximum VBUS current: ");
switch (((cable.raw_value >> 5) & 0x3)) {
case 1:
putc('3');
break;
case 2:
putc('5');
break;
default:
putc('?');
break;
}
puts("A\n");
puts("- SuperSpeed: USB ");
switch (cable.p_rev30.ss) {
case 0:
puts("2.0");
break;
case 1:
puts("3.2 Gen 1");
break;
case 2:
puts("3.2 Gen 2");
break;
default:
puts("???");
break;
}
putc('\n');
}
}
}
/** test USB-C plug
* @param[in] argument no argument required
*/
@ -1324,12 +1415,14 @@ static void command_cplug(void* argument)
printf("- CC2 %sconnected to GND (", cc2 ? "" : "not ");
print_connection(&cc2_connection);
puts(")\n");
if (cc1_connection.tx_drive_pull && cc1_connection.rx_pull_float && cc2_connection.tx_drive_pull && cc2_connection.rx_pull_float) {
puts("> powered cable to be connected to a sink on the other end (B, mini-B, or micro-B plug)\n");
} else if ((cc1_connection.tx_drive_pull && cc1_connection.rx_pull_float) || (cc2_connection.tx_drive_pull && cc2_connection.rx_pull_float)) {
puts("> powered cable, or to be connected to a sink on the other end (B, mini-B, or micro-B plug)\n");
} else {
puts("> unpowered cable\n");
if (gnd_all || vbus_all || gnd_any || vbus_any) {
if (cc1_connection.tx_drive_pull && cc1_connection.rx_pull_float && cc2_connection.tx_drive_pull && cc2_connection.rx_pull_float) {
puts("> powered cable to be connected to a sink on the other end (B, mini-B, or micro-B plug)\n");
} else if ((cc1_connection.tx_drive_pull && cc1_connection.rx_pull_float) || (cc2_connection.tx_drive_pull && cc2_connection.rx_pull_float)) {
puts("> powered cable, or to be connected to a sink on the other end (B, mini-B, or micro-B plug)\n");
} else {
puts("> unpowered cable\n");
}
}
// check if it should be connected to a source
cc1 = usb_cables_test_pins(&usb_pins[connector->pins[5]], &usb_pins[connector->pins[4]], &cc1_connection); // A5 CC1 - A4 VBUS
@ -1340,10 +1433,12 @@ static void command_cplug(void* argument)
printf("- CC2 %sconnected to VBUS (", cc2 ? "" : "not ");
print_connection(&cc2_connection);
puts(")\n");
if (cc1 || cc2) {
puts("> to be connected to a source on the other end (A plug)\n");
} else {
puts("> not to be connected to a source on the other end (A plug)\n");
if (gnd_all || vbus_all || gnd_any || vbus_any) {
if (cc1 || cc2) {
puts("> to be connected to a source on the other end (A plug)\n");
} else {
puts("> not to be connected to a source on the other end (A plug)\n");
}
}
// find out if a resistor is present using USB-C controller
if (present_fusb302 && USB_CONNECTOR_C_DEVICE == connectors[connector_id]) { // HW v1 (modified for a v2 prototype) has only a FUSB302 on the C device port
@ -1361,6 +1456,7 @@ static void command_cplug(void* argument)
gpio_set_mode(pin.port, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, pin.pin);
}
// figure out resistors on CC lines
uint8_t cc_pd = 0; // line used for PD communication
for (uint8_t cc = 1; cc < 3; cc++) {
const char* r_values[] = {"short to ground", "Ra", "Rd", "Rp", "open"};
int16_t r = usb_fusb302_r(cc);
@ -1372,13 +1468,93 @@ static void command_cplug(void* argument)
}
putc('\n');
if (1 == r) {
printf("> powered cable (CC%u is VCONN)\n", (1 == cc) ? 2 : 1);
printf("> powered cable (CC%u is CC, CC%u is VCONN)\n", (1 == cc) ? 2 : 1, cc);
cc_pd = ((1 == cc) ? 2 : 1); // remember this is the CC line to communicate with eMarker
} else if (2 == r) {
puts("> to be connected to a sink on the other end (B, mini-B, or micro-B plug)\n");
} else if (3 == r) {
puts("> to be connected to a source on the other end (A plug)\n");
}
}
if (cc_pd) { // read cable eMarker
uint8_t stage = 0;
int16_t rc = usb_fusb302_pd(cc_pd); // configure CC channel for PD communication (also flushes data)
if (rc < 0) {
stage = 1;
goto pd_end;
}
rc = usb_fusb302_discover_identity_request(); // send discover identity request
if (rc < 0) {
stage = 2;
goto pd_end;
}
sleep_ms(2); // wait tReceive = 1.1 ms for goodCRC response (PD3.0 section 6.6.1)
bool expected_message = false;
uint8_t packet[35];
while (!expected_message) { // wait got goodCRC
// I don't know why, after the first this action is called, the TX packet is also in the RX FIFO
rc = usb_fusb302_packet_read(packet);
if (0 == rc) { // RX FIFO is empty
stage = 3;
goto pd_end;
} else if (rc < 0) {
stage = 4;
goto pd_end;
}
if (6 != ((packet[0] >> 5) & 0x7)) { // not a SOP' response
continue;
}
uint16_t header = *(uint16_t*)(&packet[1]);
if (0 != PD_HEADER_CNT(header)) { // not a control message
continue;
}
if (PD_CTRL_GOOD_CRC != PD_HEADER_TYPE(header)) { // not a goodCRC message
continue;
}
expected_message = true;
}
if (!usb_fusb302_packet_checksum(packet)) { // verify CRC
stage = 5;
goto pd_end;
}
sleep_ms(15); // wait tReceiverResponse = 15 ms for request response (PD3.0 section 6.6.2)
expected_message = false;
while (!expected_message) { // wait got identity response
// I don't know why, after the first this action is called, the TX packet is also in the RX FIFO
rc = usb_fusb302_packet_read(packet);
if (0 == rc) { // RX FIFO is empty
stage = 6;
goto pd_end;
} else if (rc < 0) {
stage = 7;
goto pd_end;
}
if (6 != ((packet[0] >> 5) & 0x7)) { // not a SOP' response
continue;
}
uint16_t header = *(uint16_t*)(&packet[1]);
if (0 == PD_HEADER_CNT(header)) { // not a data message
continue;
}
if (PD_DATA_VENDOR_DEF != PD_HEADER_TYPE(header)) { // not a VDM message
continue;
}
expected_message = true;
}
if (!usb_fusb302_packet_checksum(packet)) { // verify CRC
stage = 8;
goto pd_end;
}
pd_end:
if (0 == stage) {
print_emarker(packet);
sleep_ms(2); // wait a bit for the goodCRC to be received by the eMarker
} else {
//puts("could not read eMarker\n");
printf("could not read eMarker (stage=%u, error=%d)\n", stage, rc);
}
usb_fusb302_disconnect(); // remove all CC connections
}
// put ground back to floating
usb_cables_pins_float(); // not the most efficient way, but time is not critical
}
@ -1390,7 +1566,7 @@ static void command_cplug(void* argument)
if (NULL == c1 || NULL == c2) {
return;
}
puts("cable interconnection\n");
puts("cable interconnection (C host to C device)\n");
struct usb_connection_t connection;
bool connected;
connected = usb_cables_test_pins(&usb_pins[c1->pins[5]], &usb_pins[c2->pins[5]], &connection); // A5 CC1 - A5 CC1