Dependencies:   mbed

/media/uploads/va009039/lpc1114-usb.jpg

control:
/media/uploads/va009039/lpc1114-usb-1.png

interrupt in:
/media/uploads/va009039/lpc1114-usb-2.png

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Wed Jun 18 01:33:32 2014 +0000
Commit message:
first commit

Changed in this revision

BaseUsbProtocolAnalyzer.cpp Show annotated file Show diff for this revision Revisions of this file
BaseUsbProtocolAnalyzer.h Show annotated file Show diff for this revision Revisions of this file
UsbCapture.s Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 0faa55631ffe BaseUsbProtocolAnalyzer.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BaseUsbProtocolAnalyzer.cpp	Wed Jun 18 01:33:32 2014 +0000
@@ -0,0 +1,222 @@
+#include "mbed.h"
+#include "BaseUsbProtocolAnalyzer.h"
+
+
+uint8_t crc5usb(uint16_t data)
+{
+    uint16_t r = (data&0x7ff) ^ 0x1f;
+    for(int j = 0; j < 11; j++) { // 11bit
+        if (r & 1) {
+            r = (r>>1) ^ 0x14;
+        } else {
+            r = r>>1;
+        }
+    }    
+    return r ^ 0x1f;
+}
+
+uint16_t crc16usb(const uint8_t data[], int size)
+{
+    uint16_t r = 0xffff;
+    for(int i = 0; i < size; i++) {
+        r ^= data[i];
+        for(int j = 0; j < 8; j++) {
+            if (r & 1) {
+                r = (r>>1) ^ 0xa001;
+            } else {
+                r = (r>>1);
+            }
+        }
+    }
+    return r ^ 0xffff;
+}
+
+
+BaseUsbProtocolAnalyzer::BaseUsbProtocolAnalyzer()
+{
+    init();
+}
+
+void BaseUsbProtocolAnalyzer::input(uint8_t data)
+{
+    char str[32];
+    if (data == 0) { // EOP ?
+        if (seq == SEQ_DATA) {
+            output("[");
+            for(int i = 0; i < data_count-2; i++) {
+                snprintf(str, sizeof(str), "%s0x%02x", i == 0 ? "" : " ", packet.data[i]);
+                output(str);
+            }
+            output("]");
+            if (data_count >= 2) {
+                uint16_t crc16 = packet.data[data_count-2]|(packet.data[data_count-1]<<8);
+                bool crc16_err = (crc16usb(packet.data, data_count-2) == crc16);
+                snprintf(str, sizeof(str), "[crc16=0x%04x%s]", crc16, crc16_err ? "" : " ERROR");
+                output(str);
+            }
+        }
+        output("[EOP]");
+        init();
+        return;
+    }
+
+    if (seq == SEQ_SYNC) {
+        if (disp_cycle) {
+            snprintf(str, sizeof(str), "(0x%02x)", data);
+            output(str);
+        }
+        output("[SYNC]");
+        packet.pid = (pid_t)data;
+        switch(packet.pid) {
+            case ACK:
+                output("[ACK]");
+                break;
+            case NAK:
+                output("[NAK]");
+                break;
+            case STALL:
+                output("[STALL]");
+                break;
+            case IN:
+                output("[IN]");
+                bit_count = 7;
+                break;
+            case OUT:
+                output("[OUT]");
+                bit_count = 4;
+                break;
+            case SETUP:
+                output("[SETUP]");
+                bit_count = 7;
+                break;
+            case DATA0:
+                output("[DATA0]");
+                bit_count = 5;
+                break;
+            case DATA1:
+                output("[DATA1]");
+                bit_count = 7;
+                break;
+            default:
+                snprintf(str, sizeof(str), "[pid=0x%02x]", packet.pid);
+                output(str);
+                break;
+        }
+        seq = SEQ_PID;
+        return;
+    }
+    if (disp_cycle) {
+        snprintf(str, sizeof(str), "(%d)", data);
+        output(str);
+    }
+    int n = (data + CYCLE/2) / CYCLE - 1;
+    uint8_t pat = 0;
+    int len = 0;
+    if (bit_stuffing) {
+        const uint8_t table[] = {0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
+        pat = table[n];
+        len = n;
+    } else {
+        const uint8_t table[] = {0x00,0x02,0x06,0x0e,0x1e,0x3e,0x7e,0xfe};
+        pat = table[n];    
+        len = n + 1;
+    }
+    bit_stuffing = false;
+    if (n >= 6) {
+        bit_stuffing = true;
+    }
+    inputBit(pat, len);
+}
+
+void BaseUsbProtocolAnalyzer::inputBit(uint8_t pat, int len)
+{
+    if (disp_bit) {
+        output('{');
+        for(int i = 0; i < len; i++) {
+            output(((pat>>i) & 1) ? '1' : '0');
+        }
+        output('}');
+    }
+    for(int i = 0; i < len; i++) {
+        inputLSB((pat>>i) & 1);
+    }
+}
+
+void BaseUsbProtocolAnalyzer::inputLSB(int lsb)
+{
+    char str[32];
+    seq_t prev_seq = seq;
+    switch(seq) {
+        case SEQ_PID:
+            if (++bit_count >= 8) {
+                if (packet.pid == IN || packet.pid == OUT || packet.pid == SETUP) {
+                    seq = SEQ_ADDR;
+                } else if (packet.pid == DATA0 || packet.pid == DATA1) {
+                    seq = SEQ_DATA;
+                }
+            }
+            break;
+        case SEQ_ADDR:
+            packet.addr >>= 1;
+            packet.addr |= lsb ? 0x40 : 0x00;
+            if (++bit_count >= 7) {
+                snprintf(str, sizeof(str), "[ADDR=%d]", packet.addr & 0x7f);
+                output(str);
+                seq = SEQ_ENDP;
+            }    
+            break;
+        case SEQ_ENDP:
+            packet.endp >>= 1;
+            packet.endp |= lsb ? 0x08 : 0x00;
+            if (++bit_count >= 4) {
+                snprintf(str, sizeof(str), "[ENDP=%d]", packet.endp & 0x0f);
+                output(str);
+                seq = SEQ_CRC5;
+            }
+            break;
+        case SEQ_CRC5:
+            if (bit_count < 5) {
+                packet.crc5 >>= 1;
+                packet.crc5 |= lsb ? 0x10 : 0x00;
+                if (++bit_count >= 5) {
+                    uint16_t u = packet.crc5<<11|packet.endp<<7|packet.addr;
+                    bool crc5_err = (crc5usb(u) == packet.crc5);
+                    snprintf(str, sizeof(str), "[CRC5=0x%02x%s]", 
+                        packet.crc5, crc5_err ? "" : " ERROR");
+                    output(str);
+                }
+            }
+            break;
+        case SEQ_DATA:
+            if (data_count < sizeof(packet.data)) {
+                packet.data[data_count] >>= 1;
+                packet.data[data_count] |= lsb ? 0x80 : 0x00;
+                if (++bit_count >= 8) {
+                    bit_count = 0;
+                    data_count++;
+                }
+            }
+            break;
+    }
+    if (prev_seq != seq) {
+        bit_count = 0;
+        data_count = 0;
+    }
+}
+
+void BaseUsbProtocolAnalyzer::init()
+{
+    seq = SEQ_SYNC;
+    bit_stuffing = false;
+    bit_count = 0;
+    disp_bit = false;
+    disp_cycle = false;
+}
+
+void BaseUsbProtocolAnalyzer::output(const char* s)
+{
+    while(*s) {
+        output(*s++);
+    }
+}
+
diff -r 000000000000 -r 0faa55631ffe BaseUsbProtocolAnalyzer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BaseUsbProtocolAnalyzer.h	Wed Jun 18 01:33:32 2014 +0000
@@ -0,0 +1,50 @@
+#pragma once
+
+typedef enum {
+    ACK = 0x02,
+    NAK = 0x0a,
+    STALL = 0x0e,
+    DATA0 = 0x03,
+    DATA1 = 0x0b,
+    IN = 0x09,
+    OUT = 0x01,
+    SETUP = 0x0d,
+} pid_t;
+
+typedef enum {
+    SEQ_SYNC,
+    SEQ_PID,
+    SEQ_ADDR,
+    SEQ_ENDP,
+    SEQ_CRC5,
+    SEQ_DATA,
+    SEQ_CRC16,
+} seq_t;
+
+class BaseUsbProtocolAnalyzer {
+public:
+    BaseUsbProtocolAnalyzer();
+    void init();
+    void input(uint8_t data);
+    bool disp_bit;
+    bool disp_cycle;
+protected:
+    virtual void output(char c) = 0;
+
+private:
+    static const int CYCLE = 32;
+    void inputBit(uint8_t pat, int len);
+    void inputLSB(int lsb);
+    void output(const char* s);
+    bool bit_stuffing;
+    seq_t seq;
+    struct {
+        pid_t pid;
+        uint8_t addr;
+        uint8_t endp;
+        uint8_t crc5;
+        uint8_t data[8+2]; // data and crc16
+    } packet;
+    int bit_count;
+    int data_count;
+};
diff -r 000000000000 -r 0faa55631ffe UsbCapture.s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UsbCapture.s	Wed Jun 18 01:33:32 2014 +0000
@@ -0,0 +1,250 @@
+; UsbCapture.s 2014/5/21
+;
+        AREA    USBCAPTURE,CODE,READONLY
+
+
+; uint8_t* usbcapture_lpc1114(uint8_t* buf, uint8_t* end)
+;
+;[ADDR][OUT  ][SYNC] |1110}{0}{0}{0}{1|10}{0}{0}{0}{0}{0}{0}
+;[ADDR][IN   ][SYNC] |0}{110}{10}{0}{1|10}{0}{0}{0}{0}{0}{0}
+;[ADDR][SETUP][SYNC] |0}{0}{10}{110}{1|10}{0}{0}{0}{0}{0}{0}
+;
+;[data][DATA0][SYNC] |110}{0}{0}{0}{11|10}{0}{0}{0}{0}{0}{0}
+;[data][DATA1][SYNC] |0}{10}{0}{10}{11|10}{0}{0}{0}{0}{0}{0}
+;
+;[EOP ][ACK  ][SYNC]  |110}{10}{0}{10}|{10}{0}{0}{0}{0}{0}{0}
+;[EOP ][NAK  ][SYNC]  |0}{10}{110}{10}|{10}{0}{0}{0}{0}{0}{0}
+;[EOP ][STALL][SYNC]  |0}{0}{0}{11110}|{10}{0}{0}{0}{0}{0}{0}
+;
+;{0}       :  32 cycle
+;{10}      :  64 cycle
+;{110}     :  96 cycle
+;{1110}    : 128 cycle
+;{11110}   : 160 cycle
+;{111110}  : 192 cycle
+;{1111110} : 224 cycle
+;
+
+        EXPORT    usbcapture_lpc1114
+
+CYCLE   equ     32
+GPIO1   equ     0x50010c00
+CT16B1  equ     0x40010000
+_IR     equ     0x00
+_TC     equ     0x08
+_CR0    equ     0x2c
+CR0Int  equ     (1<<4)
+
+; PID
+ACK     equ     0x02
+NAK     equ     0x0a
+STALL   equ     0x0e
+DATA0   equ     0x03
+DATA1   equ     0x0b
+IN      equ     0x09
+OUT     equ     0x01
+SETUP   equ     0x0d
+
+        MACRO
+        init_param
+        LDR     r4, =GPIO1          ; USB_DM(P1_9),USB_DP(P1_8)
+        LDR     r5, =CT16B1         ; CT16B1
+        MOVS    r6, #CR0Int         ; CR0 interrupt mask
+        MOVS    r3, #1              ; prev_CR0
+        MEND
+
+        MACRO
+        save_raw
+        STRB    r2,[r0]
+        ADDS    r0, r0, #1
+        MEND
+
+        MACRO
+        read
+1       LDR     r2, [r5,#_IR]
+        TST     r2, r6
+        BEQ     %b1
+        LDR     r2, [r5,#_CR0]
+        STR     r6, [r5,#_IR]
+        SUBS    r2, r2, r3
+        ADDS    r3, r3, r2
+        UXTB    r2, r2
+        MEND
+
+        MACRO
+        readNB  $skip
+        LDR     r2, [r5,#_IR]
+        TST     r2, r6
+        BEQ     $skip
+        LDR     r2, [r5,#_CR0]
+        STR     r6, [r5,#_IR]
+        SUBS    r2, r2, r3
+        ADDS    r3, r3, r2
+        UXTB    r2, r2
+        MEND
+
+        MACRO
+        read_TC
+        LDR     r2, [r5,#_TC]
+        SUBS    r2, r2, r3
+        ADDS    r3, r3, r2
+        UXTB    r2, r2
+        MEND
+
+        MACRO
+        if_1bit_gt $goto
+        CMP     r2, #CYCLE+CYCLE/2
+        BGT     $goto
+        MEND
+
+        MACRO
+        if_1bit_le $goto
+        CMP     r2, #CYCLE+CYCLE/2
+        BLE     $goto
+        MEND
+
+        MACRO
+        if_2bit_le $goto
+        CMP     r2, #CYCLE*2+CYCLE/2
+        BLE     $goto
+        MEND
+
+        MACRO
+        if_3bit_le $goto
+        CMP     r2, #CYCLE*3+CYCLE/2
+        BLE     $goto
+        MEND
+
+        MACRO
+        eopNB   $skip
+        LDR     r2, [r4]            ; EOP(USB_DM=0,USB_DP=0) ?
+        TST     r2, r2
+        BNE     $skip               ; no
+        MEND
+
+usbcapture_lpc1114
+CAPTURE PUSH    {r4-r7}
+        init_param
+
+SYNC
+        read
+        if_1bit_gt SYNC
+        read
+        if_1bit_gt SYNC
+        read
+        if_1bit_gt SYNC
+SYNC_67bit
+        read
+        if_1bit_le SYNC_67bit
+        if_2bit_le PID_ACK_NAK_STALL
+        if_3bit_le PID_IN_OUT_SETUP
+
+PID_DATA0_DATA1
+        read
+        if_1bit_le PID_DATA0
+
+PID_DATA1
+        read
+        read
+        MOVS    r2, #DATA1
+        save_raw
+        B       DATA_CRC16
+
+PID_DATA0
+        read
+        read
+        MOVS    r2, #DATA0
+        save_raw
+        B       DATA_CRC16
+
+PID_ACK_NAK_STALL
+        read
+        if_2bit_le PID_ACK_NAK
+
+PID_STALL
+        read
+        read
+        MOVS    r2, #STALL
+        save_raw
+        B       EOP_WAIT
+
+PID_ACK_NAK
+        read
+        if_1bit_le PID_ACK
+
+PID_NAK
+        read                ; 10b
+        read                ; 0b
+        MOVS    r2, #NAK
+        save_raw
+        B       EOP_WAIT
+
+PID_ACK
+        read
+        MOVS    r2, #ACK
+        save_raw
+        B       EOP_WAIT
+
+PID_IN_OUT_SETUP
+        read
+        if_1bit_le PID_IN_OUT
+
+PID_SETUP
+        read
+        read
+        MOVS    r2, #SETUP
+        save_raw
+        B       ADDR_ENDP_CRC5
+
+PID_IN_OUT
+        read
+        if_1bit_le PID_OUT
+
+PID_IN
+        read
+        MOVS    r2, #IN
+        save_raw
+
+DATA_CRC16
+ADDR_ENDP_CRC5
+20
+        readNB  %f30
+        save_raw
+        CMP     r0, r1
+        BGE     %f90                ; buffer full ?
+        B       %b20
+30
+        eopNB   %b20
+        STRB    r2, [r0,#1]
+        read_TC
+        STRB    r2, [r0,#0]
+        ADDS    r0, r0, #2
+        B       EOP
+
+PID_OUT
+        read
+        MOVS    r2, #OUT
+        save_raw
+        B       ADDR_ENDP_CRC5
+
+EOP_WAIT
+10
+        eopNB   %b10
+        save_raw
+        CMP     r0, r1
+        BGE     EXIT
+        B       SYNC
+EOP
+        CMP     r0, r1
+        BGE     EXIT                ; buffer full ?
+        B       SYNC
+EXIT
+90      POP     {r4-r7}
+        BX      lr                  ; return, buf = r0 
+
+ERROR   POP     {r4-r7}
+        BX      lr
+
+        ALIGN
+        END
+
diff -r 000000000000 -r 0faa55631ffe main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jun 18 01:33:32 2014 +0000
@@ -0,0 +1,66 @@
+#include "mbed.h"
+#include "BaseUsbProtocolAnalyzer.h"
+//
+//   USB    LPC1114FN28
+// 1 VCC
+// 2 DATA-  dp18(P1_9)
+// 3 DATA+  dp17(P1_8)
+// 4 GND    GND 
+
+DigitalOut led1(LED1),led2(LED2);
+DigitalIn usb_dm(P1_9);
+DigitalIn usb_dp(P1_8);
+RawSerial pc(USBTX, USBRX);
+
+const int BUF_SIZE = 512;
+uint8_t buf[BUF_SIZE+256];
+
+class USB_Protocol_Analyzer : public BaseUsbProtocolAnalyzer {
+    virtual void output(char c) {
+        pc.putc(c);
+    }
+};
+
+USB_Protocol_Analyzer analyzer;
+
+extern "C" {
+    uint8_t* usbcapture_lpc1114(uint8_t* buf, uint8_t* end);
+}
+
+void usbcapture_setup()
+{
+    usb_dm.mode(PullNone);
+    usb_dp.mode(PullNone);
+
+    LPC_SYSCON->SYSAHBCLKCTRL |= 1<<8; // CT16B1
+    LPC_IOCON->PIO1_8 = (LPC_IOCON->PIO1_8 & ~0x7) | 0x1; // FUNC=CT16B1_CAP0
+    LPC_TMR16B1->TCR |= 1; // Counter Enable
+    LPC_TMR16B1->CCR |= 7; // CAP0RE,CAP0FE,CAP0I
+}
+
+int main() {
+    pc.baud(115200);
+    pc.puts(__FILE__);
+    pc.puts("\n");
+
+    usbcapture_setup();
+
+    for(int n = 0; ; n++) {
+        uint8_t* end = usbcapture_lpc1114(buf, buf+BUF_SIZE);
+        analyzer.init();
+        for(uint8_t* p = buf; p < end; p++) {
+            analyzer.input(*p);
+            if (*p == 0) {
+                pc.puts("\n");
+            }
+        }
+        pc.puts("\n\n");
+        Timer t;
+        t.reset();
+        t.start();
+        while(t.read_ms() < 1000*3 + n%100) {
+        }
+        led1 = !led1;
+    }
+}
+
diff -r 000000000000 -r 0faa55631ffe mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Jun 18 01:33:32 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/024bf7f99721
\ No newline at end of file