application: add eMrker read out
This commit is contained in:
parent
0c5f5e8c2d
commit
9d7e4940e9
200
application.c
200
application.c
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user