BaseUsbHost example program
Dependencies: BaseUsbHost FATFileSystem mbed mbed-rtos
Revision 2:c10029b87439, committed 2012-12-11
- Comitter:
- va009039
- Date:
- Tue Dec 11 15:28:00 2012 +0000
- Parent:
- 1:80205a2de336
- Child:
- 3:6ae9a03a6145
- Commit message:
- add example
Changed in this revision
--- a/BaseUsbHost.lib Wed Dec 05 13:25:18 2012 +0000 +++ b/BaseUsbHost.lib Tue Dec 11 15:28:00 2012 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/va009039/code/BaseUsbHost/#3b7bc4f87a61 +http://mbed.org/users/va009039/code/BaseUsbHost/#fe1e62051d88
--- a/LifeCamVX700.cpp Wed Dec 05 13:25:18 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -// LifeCamVX700.cpp 2012/12/5 -#include "mbed.h" -#include "rtos.h" -#include "BaseUsbHost.h" -#define DEBUG -#include "BaseUsbHostDebug.h" -#define TEST -#include "BaseUsbHostTest.h" -#include "LifeCamVX700.h" - -LifeCamVX700::LifeCamVX700(int frameIndex, uint32_t interval, ControlEp* ctlEp) -{ - uint8_t buf[26]; - - if (ctlEp == NULL) { // root hub - DBG_OHCI(LPC_USB->HcRhPortStatus1); - TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200); - ctlEp = new ControlEp(); - TEST_ASSERT_TRUE(ctlEp); - } - bool r = check(ctlEp); - TEST_ASSERT(r); - m_ctlEp = ctlEp; - - int addr = m_ctlEp->GetAddr(); - m_isoEp = new IsochronousEp(addr, VX700_EN, VX700_MPS); - TEST_ASSERT_TRUE(m_isoEp); - - int rc = Control(GET_INFO, VS_PROBE_CONTROL, 1, buf, 1); - TEST_ASSERT(rc == USB_OK); - DBG_BYTES("GET_INFO Prob", buf, 1); - - rc = Control(GET_DEF, VS_PROBE_CONTROL, 1, buf, 26); - TEST_ASSERT(rc == USB_OK); - DBG_BYTES("GET_DEF Probe", buf, 26); - - rc = Control(GET_MIN, VS_PROBE_CONTROL, 1, buf, 26); - TEST_ASSERT(rc == USB_OK); - DBG_BYTES("GET_MIN Probe", buf, 26); - - rc = Control(GET_MAX, VS_PROBE_CONTROL, 1, buf, 26); - TEST_ASSERT(rc == USB_OK); - DBG_BYTES("GET_MAX Probe", buf, 26); - - rc = Control(GET_CUR, VS_PROBE_CONTROL, 1, buf, 26); - TEST_ASSERT(rc == USB_OK); - DBG_BYTES("GET_CUR Probe", buf, 26); - - memset(buf, 0, 26); - buf[2] = VX700_MJPEG; - buf[3] = frameIndex; - *reinterpret_cast<uint32_t*>(buf+4) = interval; - - DBG_BYTES("SET_CUR Commit", buf, 26); - rc = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, 26); - TEST_ASSERT(rc == USB_OK); - - rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, buf, 26); - TEST_ASSERT(rc == USB_OK); - TEST_ASSERT_EQUAL(buf[2], VX700_MJPEG); - TEST_ASSERT_EQUAL(buf[3], frameIndex); - TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval); - DBG_BYTES("GET_CUR Commit", buf, 26); - - int cfg; - rc = m_ctlEp->GetConfiguration(&cfg); - TEST_ASSERT_EQUAL(rc, USB_OK); - DBG("config: %d\n", cfg); - - rc = m_ctlEp->SetConfiguration(1); - TEST_ASSERT_EQUAL(rc, USB_OK); - - rc = m_ctlEp->GetConfiguration(&cfg); - TEST_ASSERT_EQUAL(rc, USB_OK); - DBG("config: %d\n", cfg); - TEST_ASSERT_EQUAL(cfg, 1); - - int alt; - rc = m_ctlEp->GetInterface(1, &alt); - TEST_ASSERT_EQUAL(rc, USB_OK); - DBG("alt: %d\n", alt); - - rc = m_ctlEp->SetInterfaceAlternate(1, VX700_IF_ALT); // alt=1 packet size = 192 - TEST_ASSERT_EQUAL(rc, USB_OK); - - rc = m_ctlEp->GetInterface(1, &alt); - TEST_ASSERT_EQUAL(rc, USB_OK); - DBG("alt: %d\n", alt); - TEST_ASSERT_EQUAL(alt, 1); - - for(int i = 0; i < 16; i++) { - report_cc_count[i] = 0; - report_ps_cc_count[i] = 0; - } - - LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable - LPC_USB->HcControl |= OR_CONTROL_IE; // IsochronousEnable -} - -bool LifeCamVX700::check(ControlEp* ctlEp) -{ - if (ctlEp == NULL) { - return false; - } - uint8_t buf[18]; - int r = ctlEp->GetDescriptor(1, 0, buf, 8); - if (r != USB_OK) { - return false; - } - DBG_HEX(buf, 8); - const uint8_t desc[] = {0x12,0x01,0x00,0x02,0xef,0x02,0x01,0x40}; - if (memcmp(buf, desc, sizeof(desc)) != 0) { - return false; - } - r = ctlEp->GetDescriptor(1, 0, buf, 18); - if (r != USB_OK) { - return false; - } - DBG_HEX(buf, 18); - uint16_t vid = *reinterpret_cast<uint16_t*>(buf+8); - uint16_t pid = *reinterpret_cast<uint16_t*>(buf+10); - DBG("VID PID: %04X %04X\n", vid, pid); - if (vid == VX700_VID && pid == VX700_PID) { - return true; - } - return false; -} -
--- a/LifeCamVX700.h Wed Dec 05 13:25:18 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -// LifeCamVX700.h 2012/12/5 -#ifndef LIFECAM_VX700_H -#define LIFECAM_VX700_H - -#define VX700_VID 0x045e -#define VX700_PID 0x074a - -#define VX700_160x120 5 -#define VX700_176x144 4 -#define VX700_320x240 3 -#define VX700_352x288 2 -#define VX700_640x480 1 - -#define VX700_MJPEG 1 - -#define VX700_EN 0x81 -#define VX700_MPS 128 -#define VX700_IF_ALT 1 - -class LifeCamVX700 : public BaseUvc{ -public: - LifeCamVX700(int frameIndex = VX700_160x120, uint32_t interval = _5FPS, ControlEp* ctlEp = NULL); - static bool check(ControlEp* ctlEp); -}; -#endif //LIFECAM_VX700_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LifeCamVX700/LifeCamVX700.cpp Tue Dec 11 15:28:00 2012 +0000 @@ -0,0 +1,99 @@ +// LifeCamVX700.cpp 2012/12/10 +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +#define DEBUG +#include "BaseUsbHostDebug.h" +#define TEST +#include "BaseUsbHostTest.h" +#include "LifeCamVX700.h" + +LifeCamVX700::LifeCamVX700(int frameIndex, uint32_t interval, ControlEp* ctlEp) +{ + uint8_t buf[26]; + + if (ctlEp == NULL) { // root hub + DBG_OHCI(LPC_USB->HcRhPortStatus1); + TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200); + ctlEp = new ControlEp(); + TEST_ASSERT_TRUE(ctlEp); + } + bool r = check(ctlEp); + TEST_ASSERT(r); + m_ctlEp = ctlEp; + + int addr = m_ctlEp->GetAddr(); + m_isoEp = new IsochronousEp(addr, VX700_EN, VX700_MPS); + TEST_ASSERT_TRUE(m_isoEp); + + memset(buf, 0, 26); + buf[2] = VX700_MJPEG; + buf[3] = frameIndex; + *reinterpret_cast<uint32_t*>(buf+4) = interval; + + DBG_BYTES("SET_CUR Commit", buf, 26); + int rc = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, 26); + TEST_ASSERT(rc == USB_OK); + + rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, buf, 26); + TEST_ASSERT(rc == USB_OK); + TEST_ASSERT_EQUAL(buf[2], VX700_MJPEG); + TEST_ASSERT_EQUAL(buf[3], frameIndex); + TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval); + DBG_BYTES("GET_CUR Commit", buf, 26); + + rc = m_ctlEp->SetConfiguration(1); + TEST_ASSERT_EQUAL(rc, USB_OK); + + int value; + rc = m_ctlEp->GetConfiguration(&value); + TEST_ASSERT_EQUAL(rc, USB_OK); + DBG("config: %d\n", value); + TEST_ASSERT_EQUAL(value, 1); + + rc = m_ctlEp->SetInterfaceAlternate(1, VX700_IF_ALT); // alt=1 packet size = 192 + TEST_ASSERT_EQUAL(rc, USB_OK); + + rc = m_ctlEp->GetInterface(1, &value); + TEST_ASSERT_EQUAL(rc, USB_OK); + DBG("alt: %d\n", value); + TEST_ASSERT_EQUAL(value, 1); + + for(int i = 0; i < 16; i++) { + report_cc_count[i] = 0; + report_ps_cc_count[i] = 0; + } + + LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable + LPC_USB->HcControl |= OR_CONTROL_IE; // IsochronousEnable +} + +bool LifeCamVX700::check(ControlEp* ctlEp) +{ + if (ctlEp == NULL) { + return false; + } + uint8_t buf[18]; + int r = ctlEp->GetDescriptor(1, 0, buf, 8); + if (r != USB_OK) { + return false; + } + DBG_HEX(buf, 8); + const uint8_t desc[] = {0x12,0x01,0x00,0x02,0xef,0x02,0x01,0x40}; + if (memcmp(buf, desc, sizeof(desc)) != 0) { + return false; + } + r = ctlEp->GetDescriptor(1, 0, buf, 18); + if (r != USB_OK) { + return false; + } + DBG_HEX(buf, 18); + uint16_t vid = *reinterpret_cast<uint16_t*>(buf+8); + uint16_t pid = *reinterpret_cast<uint16_t*>(buf+10); + DBG("VID PID: %04X %04X\n", vid, pid); + if (vid == VX700_VID && pid == VX700_PID) { + return true; + } + return false; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LifeCamVX700/LifeCamVX700.h Tue Dec 11 15:28:00 2012 +0000 @@ -0,0 +1,25 @@ +// LifeCamVX700.h 2012/12/5 +#ifndef LIFECAM_VX700_H +#define LIFECAM_VX700_H + +#define VX700_VID 0x045e +#define VX700_PID 0x074a + +#define VX700_160x120 5 +#define VX700_176x144 4 +#define VX700_320x240 3 +#define VX700_352x288 2 +#define VX700_640x480 1 + +#define VX700_MJPEG 1 + +#define VX700_EN 0x81 +#define VX700_MPS 128 +#define VX700_IF_ALT 1 + +class LifeCamVX700 : public BaseUvc{ +public: + LifeCamVX700(int frameIndex = VX700_160x120, uint32_t interval = _5FPS, ControlEp* ctlEp = NULL); + static bool check(ControlEp* ctlEp); +}; +#endif //LIFECAM_VX700_H
--- a/LogitechC270/LogitechC270.cpp Wed Dec 05 13:25:18 2012 +0000 +++ b/LogitechC270/LogitechC270.cpp Tue Dec 11 15:28:00 2012 +0000 @@ -1,4 +1,4 @@ -// LogitechC270.cpp 2012/12/5 +// LogitechC270.cpp 2012/12/11 #include "mbed.h" #include "rtos.h" #include "BaseUsbHost.h" @@ -62,31 +62,30 @@ TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval); DBG_BYTES("GET_CUR Commit", buf, 26); - int cfg; - rc = m_ctlEp->GetConfiguration(&cfg); + int value; + rc = m_ctlEp->GetConfiguration(&value); TEST_ASSERT_EQUAL(rc, USB_OK); - DBG("config: %d\n", cfg); + DBG("config: %d\n", value); rc = m_ctlEp->SetConfiguration(1); TEST_ASSERT_EQUAL(rc, USB_OK); - rc = m_ctlEp->GetConfiguration(&cfg); + rc = m_ctlEp->GetConfiguration(&value); TEST_ASSERT_EQUAL(rc, USB_OK); - DBG("config: %d\n", cfg); - TEST_ASSERT_EQUAL(cfg, 1); + DBG("config: %d\n", value); + TEST_ASSERT_EQUAL(value, 1); - int alt; - rc = m_ctlEp->GetInterface(1, &alt); + rc = m_ctlEp->GetInterface(1, &value); TEST_ASSERT_EQUAL(rc, USB_OK); - DBG("alt: %d\n", alt); + DBG("alt: %d\n", value); rc = m_ctlEp->SetInterfaceAlternate(1, C270_IF_ALT); // alt=1 packet size = 192 TEST_ASSERT_EQUAL(rc, USB_OK); - rc = m_ctlEp->GetInterface(1, &alt); + rc = m_ctlEp->GetInterface(1, &value); TEST_ASSERT_EQUAL(rc, USB_OK); - DBG("alt: %d\n", alt); - TEST_ASSERT_EQUAL(alt, 1); + DBG("alt: %d\n", value); + TEST_ASSERT_EQUAL(value, C270_IF_ALT); for(int i = 0; i < 16; i++) { report_cc_count[i] = 0; @@ -125,4 +124,3 @@ } return false; } -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyThread/MyThread.h Tue Dec 11 15:28:00 2012 +0000 @@ -0,0 +1,52 @@ +// MyThread.h 2012/12/9 +#ifndef MY_THREAD_H +#define MY_THREAD_H + +#define MAGIC_WORD 0xE25A2EA5 +static void thread_handler(void const *argument); + +class MyThread { +public: + MyThread() { + m_stack_size = DEFAULT_STACK_SIZE; + m_stack_pointer = NULL; + } + void set_stack(uint32_t stack_size=DEFAULT_STACK_SIZE, uint8_t* stack_pointer = NULL) { + m_stack_size = stack_size; + m_stack_pointer = stack_pointer; + } + virtual void run() = 0; + Thread* start(osPriority priority=osPriorityNormal) { + if (m_stack_pointer == NULL) { + m_stack_pointer = reinterpret_cast<uint8_t*>(malloc(m_stack_size)); + } + for(int i = 0; i < m_stack_size-64; i += 4) { + *reinterpret_cast<uint32_t*>(m_stack_pointer+i) = MAGIC_WORD; + } + return th = new Thread(thread_handler, this, priority, m_stack_size, m_stack_pointer); + } + + int stack_used() { + int i; + for(i = 0; i < m_stack_size; i += 4) { + if(*reinterpret_cast<uint32_t*>(m_stack_pointer+i) != MAGIC_WORD) { + break; + } + } + return m_stack_size - i; + } + + int stack_size() { return m_stack_size; } +protected: + Thread* th; + uint32_t m_stack_size; + uint8_t* m_stack_pointer; +}; +static void thread_handler(void const *argument) { + MyThread* th = (MyThread*)argument; + if (th) { + th->run(); + } +} + +#endif //MY_THREAD_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UvcCam/UvcCam.cpp Tue Dec 11 15:28:00 2012 +0000 @@ -0,0 +1,566 @@ +// UvcCam.cpp 2012/12/9 +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +#define DEBUG +#include "BaseUsbHostDebug.h" +#define TEST +#include "BaseUsbHostTest.h" +#include "UvcCam.h" + +UvcCam::UvcCam(int formatIndex, int frameIndex, uint32_t interval, ControlEp* ctlEp) +{ + uint8_t buf[34]; + int rc; + int alt; + int cfg2; + + if (ctlEp == NULL) { // root hub + DBG_OHCI(LPC_USB->HcRhPortStatus1); + TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200); + ctlEp = new ControlEp(); + TEST_ASSERT_TRUE(ctlEp); + } + bool r = check(ctlEp); + TEST_ASSERT(r); + m_ctlEp = ctlEp; + + UvcCfg* cfg = new UvcCfg(formatIndex, frameIndex, ctlEp); + TEST_ASSERT(cfg); + + int param_len = 34; + TEST_ASSERT(cfg->bcdUVC >= 0x0100); + if (cfg->bcdUVC == 0x0100) { // UVC ver. 1.0 + param_len = 26; + } + + int addr = m_ctlEp->GetAddr(); + m_isoEp = new IsochronousEp(addr, cfg->bEndpointAddress, cfg->wMaxPacketSize); + TEST_ASSERT_TRUE(m_isoEp); + +//#define USE_PROBE + +#ifdef USE_PROBE + rc = Control(GET_INFO, VS_PROBE_CONTROL, 1, buf, 1); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GET_INFO Prob", buf, 1); + + rc = Control(GET_DEF, VS_PROBE_CONTROL, 1, buf, param_len); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GET_DEF Probe", buf, param_len); + + rc = Control(GET_MIN, VS_PROBE_CONTROL, 1, buf, param_len); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GET_MIN Probe", buf, param_len); + + rc = Control(GET_MAX, VS_PROBE_CONTROL, 1, buf, param_len); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GET_MAX Probe", buf, param_len); + + rc = Control(GET_CUR, VS_PROBE_CONTROL, 1, buf, param_len); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GET_CUR Probe", buf, param_len); +#endif // USE_PROBE + + rc = Control(GET_INFO, VS_COMMIT_CONTROL, 1, buf, 1); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GET_INFO Commit", buf, 1); + + memset(buf, 0, param_len); + buf[2] = cfg->FormatIndex; + buf[3] = cfg->FrameIndex; + *reinterpret_cast<uint32_t*>(buf+4) = interval; + + DBG_BYTES("SET_CUR Commit", buf, param_len); + rc = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, param_len); + TEST_ASSERT(rc == USB_OK); + + rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, buf, param_len); + TEST_ASSERT(rc == USB_OK); + TEST_ASSERT_EQUAL(buf[2], cfg->FormatIndex); + TEST_ASSERT_EQUAL(buf[3], cfg->FrameIndex); + TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval); + DBG_BYTES("GET_CUR Commit", buf, param_len); + + rc = m_ctlEp->GetConfiguration(&cfg2); + TEST_ASSERT_EQUAL(rc, USB_OK); + DBG("config: %d\n", cfg2); + + rc = m_ctlEp->SetConfiguration(1); + TEST_ASSERT_EQUAL(rc, USB_OK); + + rc = m_ctlEp->GetConfiguration(&cfg2); + TEST_ASSERT_EQUAL(rc, USB_OK); + DBG("config: %d\n", cfg2); + TEST_ASSERT_EQUAL(cfg2, 1); + + rc = m_ctlEp->GetInterface(cfg->bInterface, &alt); + TEST_ASSERT_EQUAL(rc, USB_OK); + DBG("alt: %d\n", alt); + + rc = m_ctlEp->SetInterfaceAlternate(cfg->bInterface, cfg->bAlternate); + TEST_ASSERT_EQUAL(rc, USB_OK); + + rc = m_ctlEp->GetInterface(cfg->bInterface, &alt); + TEST_ASSERT_EQUAL(rc, USB_OK); + DBG("alt: %d\n", alt); + TEST_ASSERT_EQUAL(alt, cfg->bAlternate); + delete cfg; + + for(int i = 0; i < 16; i++) { + report_cc_count[i] = 0; + report_ps_cc_count[i] = 0; + } + + LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable + LPC_USB->HcControl |= OR_CONTROL_IE; // IsochronousEnable +} + +bool UvcCam::check(ControlEp* ctlEp) +{ + if (ctlEp == NULL) { + return false; + } + uint8_t buf[18]; + int r = ctlEp->GetDescriptor(1, 0, buf, 8); + if (r != USB_OK) { + return false; + } + DBG_HEX(buf, 8); + const uint8_t desc[] = {0x12,0x01,0x00,0x02,0xef,0x02,0x01}; + if (memcmp(buf, desc, sizeof(desc)) != 0) { + return false; + } + r = ctlEp->GetDescriptor(1, 0, buf, 18); + if (r != USB_OK) { + return false; + } + DBG_HEX(buf, 18); + return true; +} + +#define DESCRIPTOR_TYPE_DEVICE 1 +#define DESCRIPTOR_TYPE_CONFIGURATION 2 +#define DESCRIPTOR_TYPE_STRING 3 +#define DESCRIPTOR_TYPE_INTERFACE 4 +#define DESCRIPTOR_TYPE_ENDPOINT 5 + +#define DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0b + +#define DESCRIPTOR_TYPE_HID 0x21 +#define DESCRIPTOR_TYPE_REPORT 0x22 +#define DESCRIPTOR_TYPE_PHYSICAL 0x23 +#define DESCRIPTOR_TYPE_CS_INTERFACE 0x24 +#define DESCRIPTOR_TYPE_CS_ENDPOINT 0x25 +#define DESCRIPTOR_TYPE_HUB 0x29 + +#define CLASS_AUDIO 0x02 +#define CLASS_HUB 0x09 + +#define IF_EQ_THEN_PRINTF(A,B) if (A == B) {VERBOSE("%s\n", #A); +#define ENDIF } + +#define CC_AUDIO 0x01 +#define SC_AUDIOCONTROL 0x01 +#define SC_AUDIOSTREAMING 0x02 + +#define AC_HEADER 0x01 +#define AC_INPUT_TERMINAL 0x02 +#define AC_OUTPUT_TERMINAL 0x03 +#define AC_FEATURE_UNIT 0x06 + +// Input Terminal Types +#define ITT_CAMERA 0x0201 + +static int LE16(const uint8_t* d) +{ + return d[0] | (d[1] << 8); +} + +static int LE24(const uint8_t* d) { + return d[0] | (d[1]<<8) | (d[2] << 16); +} + +static int LE32(const uint8_t* d) { + return d[0] |(d[1]<<8) | (d[2] << 16) |(d[3] << 24) ; +} + +UvcCfg::UvcCfg(int formatIndex, int frameIndex, ControlEp* ctlEp):wMaxPacketSize(0) +{ + TEST_ASSERT(ctlEp); + switch(formatIndex) { + case UVC_MJPEG: _payload = UVC_MJPEG; break; + case UVC_YUY2: _payload = UVC_YUY2; break; + default: _payload = UVC_MJPEG; break; + } + + switch(frameIndex) { + case UVC_160x120: _width = 160; _height = 120; break; + case UVC_176x144: _width = 176; _height = 144; break; + case UVC_320x176: _width = 320; _height = 176; break; + case UVC_320x240: _width = 320; _height = 240; break; + case UVC_352x288: _width = 352; _height = 288; break; + case UVC_432x240: _width = 432; _height = 240; break; + case UVC_640x480: _width = 640; _height = 480; break; + case UVC_544x288: _width = 544; _height = 288; break; + case UVC_640x360: _width = 640; _height = 360; break; + case UVC_752x416: _width = 752; _height = 416; break; + case UVC_800x448: _width = 800; _height = 448; break; + case UVC_800x600: _width = 800; _height = 600; break; + default: _width = 160; _height = 120; break; + } + int index = 0; + uint8_t temp[4]; + int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, temp, sizeof(temp)); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("Config Descriptor 4bytes", temp, sizeof(temp)); + TEST_ASSERT(temp[0] == 9); + TEST_ASSERT(temp[1] == 0x02); + int TotalLength = LE16(temp+2); + DBG("TotalLength: %d\n", TotalLength); + + uint8_t* buf = new uint8_t[TotalLength]; + TEST_ASSERT(buf); + rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, TotalLength); + TEST_ASSERT(rc == USB_OK); + if (rc != USB_OK) { + delete[] buf; + return; + } + _parserConfigurationDescriptor(buf, TotalLength); + delete[] buf; +} + +void UvcCfg::_parserAudioControl(uint8_t* buf, int len) { + int subtype = buf[2]; + IF_EQ_THEN_PRINTF(AC_HEADER, subtype) + VERBOSE("ADC: %04x\n", LE16(buf+3)); + VERBOSE("TotalLength: %d\n", LE16(buf+5)); + VERBOSE("InCollection: %d\n", buf[7]); + for (int n = 1; n <= buf[7]; n++) { + VERBOSE("aInterfaceNr(%d): %d\n", n, buf[8+n-1]); + } + ENDIF + IF_EQ_THEN_PRINTF(AC_INPUT_TERMINAL, subtype) + VERBOSE("TerminalID: %d\n", buf[3]); + VERBOSE("TerminalType: %04X\n", LE16(buf+4)); + VERBOSE("AssocTermianl: %d\n", buf[6]); + VERBOSE("NrChannels: %d\n", buf[7]); + ENDIF + IF_EQ_THEN_PRINTF(AC_OUTPUT_TERMINAL, subtype) + VERBOSE("TerminalID: %d\n", buf[3]); + VERBOSE("TerminalType: %04X\n", LE16(buf+4)); + VERBOSE("AssocTermianl: %d\n", buf[6]); + ENDIF + IF_EQ_THEN_PRINTF(AC_FEATURE_UNIT, subtype) + VERBOSE("UnitID: %d\n", buf[3]); + VERBOSE("SourceID: %d\n", buf[4]); + VERBOSE("ControlSize: %d\n", buf[5]); + ENDIF +} + +#define AS_GENERAL 0x01 +#define AS_FORMAT_TYPE 0x02 + +void UvcCfg::_parserAudioStream(uint8_t* buf, int len) { + int subtype = buf[2]; + IF_EQ_THEN_PRINTF(AS_GENERAL, subtype) + VERBOSE("TerminalLink: %d\n", buf[3]); + VERBOSE("Delay: %d\n", buf[4]); + VERBOSE("FormatTag: %04x\n", LE16(buf+5)); + ENDIF + IF_EQ_THEN_PRINTF(AS_FORMAT_TYPE, subtype) + VERBOSE("FormatType: %d\n", buf[3]); + VERBOSE("NrChannels: %d\n", buf[4]); + VERBOSE("SubFrameSize: %d\n", buf[5]); + VERBOSE("BitResolution: %d\n", buf[6]); + VERBOSE("SamFreqType: %d\n", buf[7]); + VERBOSE("SamFreq(1): %d\n", LE24(buf+8)); + ENDIF +} + +#define CC_VIDEO 0x0e + +#define SC_VIDEOCONTROL 0x01 +#define SC_VIDEOSTREAMING 0x02 + +#define VC_HEADER 0x01 +#define VC_INPUT_TERMINAL 0x02 +#define VC_OUTPUT_TERMINAL 0x03 +#define VC_SELECTOR_UNIT 0x04 +#define VC_PROCESSING_UNIT 0x05 +#define VC_EXTENSION_UNIT 0x06 + +void UvcCfg::_parserVideoControl(uint8_t* buf, int len) { + int subtype = buf[2]; + IF_EQ_THEN_PRINTF(VC_HEADER, subtype) + bcdUVC = LE16(buf+3); + VERBOSE("UVC: %04x\n", bcdUVC); + VERBOSE("TotalLength: %d\n", LE16(buf+5)); + VERBOSE("ClockFrequency: %d\n", LE32(buf+7)); + VERBOSE("InCollection: %d\n", buf[11]); + VERBOSE("aInterfaceNr(1): %d\n", buf[12]); + ENDIF + IF_EQ_THEN_PRINTF(VC_INPUT_TERMINAL, subtype) + VERBOSE("TerminalID: %d\n", buf[3]); + uint16_t tt = LE16(buf+4); + VERBOSE("TerminalType: %04X\n", tt); + VERBOSE("AssocTerminal: %d\n", buf[6]); + VERBOSE("Terminal: %d\n", buf[7]); + if (tt == ITT_CAMERA) { // camera + int bControlSize = buf[14]; + VERBOSE("ControlSize: %d\n", bControlSize); + for(int i = 0; i < bControlSize; i++) { + uint8_t bControls = buf[15+i]; + VERBOSE("Controls(%d): %02X\n", i, bControls); + } + } + ENDIF + IF_EQ_THEN_PRINTF(VC_OUTPUT_TERMINAL, subtype) + VERBOSE("TerminalID: %d\n", buf[3]); + VERBOSE("TerminalType: %04X\n", LE16(buf+4)); + VERBOSE("AssocTerminal: %d\n", buf[6]); + VERBOSE("SourceID: %d\n", buf[7]); + VERBOSE("Terminal: %d\n", buf[8]); + ENDIF + IF_EQ_THEN_PRINTF(VC_SELECTOR_UNIT, subtype) + VERBOSE("UnitID: %d\n", buf[3]); + ENDIF + IF_EQ_THEN_PRINTF(VC_PROCESSING_UNIT, subtype) + VERBOSE("UnitID: %d\n", buf[3]); + VERBOSE("SourceID: %d\n", buf[4]); + VERBOSE("MaxMultiplier: %d\n", LE16(buf+5)); + VERBOSE("ControlSize: %d\n", buf[7]); + int pos = 8; + for (int n = 1; n <= buf[7]; n++) { + VERBOSE("Controls(%d): %02X\n", n , buf[pos]); + pos++; + } + VERBOSE("Processing: %d\n", buf[pos]); + pos++; + VERBOSE("VideoStanders: %02X\n", buf[pos]); + ENDIF + IF_EQ_THEN_PRINTF(VC_EXTENSION_UNIT, subtype) + VERBOSE("UnitID: %d\n", buf[3]); + ENDIF +} + +#define VS_INPUT_HEADER 0x01 +#define VS_STILL_FRAME 0x03 +#define VS_FORMAT_UNCOMPRESSED 0x04 +#define VS_FRAME_UNCOMPRESSED 0x05 +#define VS_FORMAT_MJPEG 0x06 +#define VS_FRAME_MJPEG 0x07 +#define VS_COLOR_FORMAT 0x0d + +void UvcCfg::_parserVideoStream(uint8_t* buf, int len) { + int subtype = buf[2]; + IF_EQ_THEN_PRINTF(VS_INPUT_HEADER, subtype) + VERBOSE("NumFormats: %d\n", buf[3]); + VERBOSE("TotalLength: %d\n", LE16(buf+4)); + VERBOSE("EndpointAddress: %02X\n", buf[6]); + VERBOSE("Info: %02X\n", buf[7]); + VERBOSE("TerminalLink: %d\n", buf[8]); + VERBOSE("StillCaptureMethod: %d\n", buf[9]); + VERBOSE("TriggerSupport: %d\n", buf[10]); + VERBOSE("TriggerUsage: %d\n", buf[11]); + VERBOSE("ControlSize: %d\n", buf[12]); + int pos = 13; + for (int n = 1; n <= buf[12]; n++) { + VERBOSE("Controls(%d): %02X\n", n, buf[pos]); + pos++; + } + bEndpointAddress = buf[6]; + ENDIF + IF_EQ_THEN_PRINTF(VS_STILL_FRAME, subtype) + VERBOSE("EndpointAdress: %02X\n", buf[3]); + VERBOSE("NumImageSizePatterns: %d\n", buf[4]); + int ptn = buf[4]; + int pos = 5; + for (int n = 1; n <= ptn; n++) { + VERBOSE("Width(%d): %d\n", n, LE16(buf+pos)); + VERBOSE("Height(%d): %d\n", n, LE16(buf+pos+2)); + pos += 4; + } + VERBOSE("NumCompressPtn: %d\n", buf[pos]); + ptn = buf[pos++]; + for (int n = 1; n <= ptn; n++) { + VERBOSE("Compress(%d): %d\n", n, buf[pos]); + pos++; + } + ENDIF + IF_EQ_THEN_PRINTF(VS_FORMAT_UNCOMPRESSED, subtype) + VERBOSE("FormatIndex: %d\n", buf[3]); + VERBOSE("NumFrameDescriptors: %d\n", buf[4]); + uint32_t guid = LE32(buf+5); + if (guid == 0x32595559) { + VERBOSE("GUID: YUY2\n"); + } else if (guid == 0x3231564e) { + VERBOSE("GUID: NV12\n"); + } else { + VERBOSE("GUID: %08x\n", guid); + } + VERBOSE("DefaultFrameIndex: %d\n", buf[22]); + if (_payload == UVC_YUY2) { + FormatIndex = buf[3]; + } + ENDIF + IF_EQ_THEN_PRINTF(VS_FRAME_UNCOMPRESSED, subtype) + VERBOSE("FrameIndex: %d\n", buf[3]); + VERBOSE("Capabilites: %d\n", buf[4]); + VERBOSE("Width: %d\n", LE16(buf+5)); + VERBOSE("Height: %d\n", LE16(buf+7)); + VERBOSE("MinBitRate: %d\n", LE32(buf+9)); + VERBOSE("MaxBitRate: %d\n", LE32(buf+13)); + VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17)); + VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21)); + VERBOSE("FrameIntervalType: %d\n", buf[25]); + int it = buf[25]; + uint32_t max_fi = 333333; // 30.0fps + if (it == 0) { + VERBOSE("FrameMinInterval: %d\n", buf[26]); + VERBOSE("FrameMaxInterval: %d\n", buf[30]); + VERBOSE("FrameIntervalStep: %d\n", buf[34]); + } else { + int pos = 26; + for (int n = 1; n <= it; n++) { + uint32_t fi = LE32(buf+pos); + if (fi >= max_fi) { + max_fi = fi; + } + float fps = 1e+7 / fi; + VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps); + pos += 4; + } + } + if (_payload == UVC_YUY2) { + if (_width == LE16(buf+5) && _height == LE16(buf+7)) { + FrameIndex = buf[3]; + } + if (dwFrameInterval == 0) { + dwFrameInterval = max_fi; + } + } + ENDIF + IF_EQ_THEN_PRINTF(VS_FORMAT_MJPEG, subtype) + VERBOSE("FormatIndex: %d\n", buf[3]); + VERBOSE("NumFrameDescriptors: %d\n", buf[4]); + VERBOSE("Flags: %d\n", buf[5]); + VERBOSE("DefaultFrameIndex: %d\n", buf[6]); + if (_payload == UVC_MJPEG) { + FormatIndex = buf[3]; + } + ENDIF + IF_EQ_THEN_PRINTF(VS_FRAME_MJPEG, subtype) + VERBOSE("FrameIndex: %d\n", buf[3]); + VERBOSE("Capabilites: %d\n", buf[4]); + VERBOSE("Width: %d\n", LE16(buf+5)); + VERBOSE("Height: %d\n", LE16(buf+7)); + VERBOSE("MinBitRate: %d\n", LE32(buf+9)); + VERBOSE("MaxBitRate: %d\n", LE32(buf+13)); + VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17)); + VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21)); + VERBOSE("FrameIntervalType: %d\n", buf[25]); + int it = buf[25]; + uint32_t max_fi = 333333; // 30.0fps + if (it == 0) { + VERBOSE("FrameMinInterval: %d\n", buf[26]); + VERBOSE("FrameMaxInterval: %d\n", buf[30]); + VERBOSE("FrameIntervalStep: %d\n", buf[34]); + } else { + int pos = 26; + for (int n = 1; n <= it; n++) { + uint32_t fi = LE32(buf+pos); + if (fi >= max_fi) { + max_fi = fi; + } + float fps = 1e+7 / fi; + VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps); + pos += 4; + } + } + if (_payload == UVC_MJPEG) { + if (_width == LE16(buf+5) && _height == LE16(buf+7)) { + FrameIndex = buf[3]; + } + if (dwFrameInterval == 0) { + dwFrameInterval = max_fi; + } + } + ENDIF + IF_EQ_THEN_PRINTF(VS_COLOR_FORMAT, subtype) + ENDIF +} + +void UvcCfg::_parserConfigurationDescriptor(uint8_t* buf, int len) { + int pos = 0; + _IfClass = 0; + _IfSubClass = 0; + while (pos < len) { + int type = buf[pos+1]; + //DBG_BYTES(TYPE_Str(type), buf+pos, buf[pos]); + IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CONFIGURATION, type) + VERBOSE("NumInterfaces: %d\n", buf[pos+4]); + ENDIF + IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, type) + VERBOSE("FirstInterface: %d\n", buf[pos+2]); + VERBOSE("InterfaceCount: %d\n", buf[pos+3]); + VERBOSE("FunctionClass: %02X\n", buf[pos+4]); + VERBOSE("FunctionSubClass: %02X\n", buf[pos+5]); + VERBOSE("FunctionProtocol: %02X\n", buf[pos+6]); + VERBOSE("Function: %d\n", buf[pos+7]); + ENDIF + IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE,type) + VERBOSE("InterfaceNumber: %d\n", buf[pos+2]); + VERBOSE("AlternateSetting: %d\n", buf[pos+3]); + VERBOSE("NumEndpoint: %d\n", buf[pos+4]); + VERBOSE("InterfaceClass: %02X\n", buf[pos+5]); + VERBOSE("InterfaceSubClass: %02X\n", buf[pos+6]); + VERBOSE("InterfaceProtocol: %02X\n", buf[pos+7]); + VERBOSE("Interface: %d\n", buf[pos+8]); + _If = buf[pos+2]; + _Ifalt = buf[pos+3]; + _IfClass = buf[pos+5]; + _IfSubClass = buf[pos+6]; + ENDIF + IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_ENDPOINT, type) + VERBOSE("EndpointAddress: %02X\n", buf[pos+2]); + VERBOSE("Attributes: %02X\n", buf[pos+3]); + VERBOSE("MaxPacketSize: %d\n", LE16(buf+pos+4)); + VERBOSE("Interval: %d\n", buf[pos+6]); + if (_IfClass == CC_VIDEO && _IfSubClass == SC_VIDEOSTREAMING) { + if (bEndpointAddress == buf[pos+2]) { + if (wMaxPacketSize == 0) { + wMaxPacketSize = LE16(buf+pos+4); + } + if (wMaxPacketSize == LE16(buf+pos+4)) { + bInterface = _If; + bAlternate = _Ifalt; + } + } + } + ENDIF + IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CS_INTERFACE, type) + IF_EQ_THEN_PRINTF(CC_VIDEO, _IfClass) + IF_EQ_THEN_PRINTF(SC_VIDEOCONTROL, _IfSubClass) + _parserVideoControl(buf+pos, buf[pos]); + ENDIF + IF_EQ_THEN_PRINTF(SC_VIDEOSTREAMING, _IfSubClass) + _parserVideoStream(buf+pos, buf[pos]); + ENDIF + ENDIF + IF_EQ_THEN_PRINTF(CC_AUDIO, _IfClass) + IF_EQ_THEN_PRINTF(SC_AUDIOCONTROL, _IfSubClass) + _parserAudioControl(buf+pos, buf[pos]); + ENDIF + IF_EQ_THEN_PRINTF(SC_AUDIOSTREAMING, _IfSubClass) + _parserAudioStream(buf+pos, buf[pos]); + ENDIF + ENDIF + ENDIF + IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_HUB, type) + ENDIF + pos += buf[pos]; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UvcCam/UvcCam.h Tue Dec 11 15:28:00 2012 +0000 @@ -0,0 +1,55 @@ +// UvcCam.h 2012/12/9 +#ifndef UVC_CAM_H +#define UVC_CAM_H + +#define UVC_160x120 2 +#define UVC_176x144 3 +#define UVC_320x176 4 +#define UVC_320x240 5 +#define UVC_352x288 6 +#define UVC_432x240 7 +#define UVC_640x480 1 +#define UVC_544x288 8 +#define UVC_640x360 9 +#define UVC_752x416 10 +#define UVC_800x448 11 +#define UVC_800x600 12 + +#define UVC_MJPEG 2 +#define UVC_YUY2 1 + +#define VERBOSE(...) do{printf(__VA_ARGS__);} while(0); + +class UvcCam : public BaseUvc { +public: + UvcCam(int formatIndex = UVC_MJPEG, int frameIndex = UVC_160x120, uint32_t interval = _5FPS, ControlEp* ctlEp = NULL); + static bool check(ControlEp* ctlEp); +}; + +class UvcCfg { +public: + UvcCfg(int formatIndex, int frameIndex, ControlEp* ctlEp); + uint8_t bEndpointAddress; + uint16_t wMaxPacketSize; + uint8_t FormatIndex; + uint8_t FrameIndex; + uint32_t dwFrameInterval; + uint8_t bInterface; + uint8_t bAlternate; + uint16_t bcdUVC; +protected: + void _parserAudioControl(uint8_t* buf, int len); + void _parserAudioStream(uint8_t* buf, int len); + void _parserVideoControl(uint8_t* buf, int len); + void _parserVideoStream(uint8_t* buf, int len); + void _parserConfigurationDescriptor(uint8_t* buf, int len); + uint16_t _width; + uint16_t _height; + uint8_t _payload; + int _If; + int _Ifalt; + int _IfClass; + int _IfSubClass; +}; + +#endif //UVC_CAM_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/decodeMJPEG/decodeMJPEG.cpp Tue Dec 11 15:28:00 2012 +0000 @@ -0,0 +1,180 @@ +// decodeMJPEG.cpp 2012/12/8 +// decode motion-jpeg to jpeg +#include "mbed.h" +#include "decodeMJPEG.h" + +#define MARK_SOF0 0xc0 +#define MARK_DHT 0xc4 +#define MARK_RST0 0xd0 +#define MARK_RST7 0xd7 +#define MARK_SOI 0xd8 +#define MARK_EOI 0xd9 +#define MARK_SOS 0xda +#define MARK_DQT 0xdb +#define MARK_DRI 0xdd +#define MARK_APP 0xe0 + +#define SEQ_INIT 0 +#define SEQ_SOI 1 +#define SEQ_FRAME 2 +#define SEQ_MARK 3 +#define SEQ_SEG_LEN 4 +#define SEQ_SEG_LEN2 5 +#define SEQ_SEG_BODY 6 +#define SEQ_SOS 7 +#define SEQ_SOS2 8 + +static const uint8_t dht[] = { +0xFF,0xC4,0x01,0xA2,0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A, +0x0B,0x01,0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00, +0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x10,0x00, +0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D,0x01, +0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22, +0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24, +0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29, +0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A, +0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A, +0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A, +0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8, +0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6, +0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,0xE3, +0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9, +0xFA,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01, +0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07, +0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33, +0x52,0xF0,0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19, +0x1A,0x26,0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46, +0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66, +0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85, +0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3, +0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA, +0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8, +0xD9,0xDA,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6, +0xF7,0xF8,0xF9,0xFA, +}; + +decodeMJPEG::decodeMJPEG() +{ + m_seq = SEQ_INIT; +} + +void decodeMJPEG::inputPacket(const uint8_t* buf, int len) +{ + for(int i = 12; i < len; i++) { + input(buf[i]); + } +} + +void decodeMJPEG::input(uint8_t c) +{ + switch(m_seq) { + case SEQ_INIT: + if (c == 0xff) { + m_seq = SEQ_SOI; + } + break; + case SEQ_SOI: + if (c == MARK_SOI) { + outputJPEG(0xff, JPEG_START); // start + outputJPEG(c); + m_bDHT = false; + m_seq = SEQ_FRAME; + } else { + m_seq = SEQ_INIT; + } + break; + case SEQ_FRAME: + if (c == 0xff) { + m_seq = SEQ_MARK; + } else { + m_seq = SEQ_INIT; + } + break; + case SEQ_MARK: + if (c == MARK_SOI || c == MARK_EOI || c == 0x00) { + m_seq = SEQ_INIT; + break; + } + m_mark = c; + m_seq = SEQ_SEG_LEN; + break; + case SEQ_SEG_LEN: + m_seg_len = c; + m_seq = SEQ_SEG_LEN2; + break; + case SEQ_SEG_LEN2: + m_seg_len <<= 8; + m_seg_len |= c; + m_seg_len -= 2; + m_seg_pos = 0; + m_seq = SEQ_SEG_BODY; + if (m_mark == MARK_SOS) { + if (m_bDHT == false) { + for(int i = 0; i < sizeof(dht); i++) { + outputJPEG(dht[i]); + } + } + m_output_desable = false; + } else if (m_mark == MARK_DHT) { + m_bDHT = true; + m_output_desable = false; + } else { + m_output_desable = false; + } + if (!m_output_desable) { + outputJPEG(0xff); + outputJPEG(m_mark); + outputJPEG((m_seg_len+2) >> 8); + outputJPEG((m_seg_len+2) & 0xff); + } + break; + case SEQ_SEG_BODY: + if (!m_output_desable) { + outputJPEG(c); + } + if (++m_seg_pos < m_seg_len) { + break; + } + if (m_mark == MARK_SOS) { + m_seq = SEQ_SOS; + break; + } + m_seq = SEQ_FRAME; + break; + case SEQ_SOS: + if (c == 0xff) { + m_seq = SEQ_SOS2; + break; + } + outputJPEG(c); + break; + case SEQ_SOS2: + if (c == 0x00) { + outputJPEG(0xff); + outputJPEG(0x00); + m_seq = SEQ_SOS; + break; + } else if (c >= MARK_RST0 && c <= MARK_RST7) { + outputJPEG(0xff); + outputJPEG(c); + m_seq = SEQ_SOS; + break; + } else if (c == MARK_EOI) { + outputJPEG(0xff); + outputJPEG(c, JPEG_END); + m_seq = SEQ_INIT; + break; + } else if (c == MARK_SOI) { + outputJPEG(0xff); + outputJPEG(c); + m_seq = SEQ_INIT; + break; + } + m_seq = SEQ_INIT; + break; + default: + m_seq = SEQ_INIT; + break; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/decodeMJPEG/decodeMJPEG.h Tue Dec 11 15:28:00 2012 +0000 @@ -0,0 +1,25 @@ +// decodeMJPEG.h 2012/12/9 +#ifndef DECODE_MJPEG_H +#define DECODE_MJPEG_H + +#define JPEG_NONE 0 +#define JPEG_START 1 +#define JPEG_END 2 +#define JPEG_ERROR 3 + +class decodeMJPEG { +public: + decodeMJPEG(); + void inputPacket(const uint8_t* buf, int len); + virtual void outputJPEG(uint8_t c, int status = JPEG_NONE) = 0; +protected: + void input(uint8_t c); + int m_seq; + uint8_t m_mark; + uint16_t m_seg_pos; + uint16_t m_seg_len; + bool m_bDHT; + bool m_output_desable; +}; + +#endif // DECODE_MJPEG_H
--- a/example1_LogitechC270.cpp Wed Dec 05 13:25:18 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -#if 1 -// -// simple color tracking -// -#include "mbed.h" -#include "rtos.h" -#include "BaseUsbHost.h" -#define DEBUG -#include "BaseUsbHostDebug.h" -#define TEST -#include "BaseUsbHostTest.h" -#include "LogitechC270.h" -#include "BaseJpegDecode.h" -#include "Terminal.h" - -// Logitech C270 -#define WIDTH 160 -#define HEIGHT 120 - -#define THRESHOLD 200 - -DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); -Terminal term(USBTX, USBRX); - -class CalcCenter : public BaseJpegDecode { -public: - int y_center, x_center; - int m_x_sum, m_y_sum, m_sum; - uint32_t EOI_count; - int16_t m_buf[WIDTH/16*HEIGHT/8]; - CalcCenter():EOI_count(0) { - memset(m_buf, 0, sizeof(m_buf)); - } - virtual void outputDC(int mcu, int block, int value) { - if (mcu >= (WIDTH/16*HEIGHT/8)) { - return; - } - if (block == 3) { // 0-1:Y 2:Cb 3:Cr - value *= qt[1][0]; - m_buf[mcu] = value; // debug - if (value >= THRESHOLD) { // red - m_x_sum += value*(mcu%(WIDTH/16)); - m_y_sum += value*(mcu/(WIDTH/16)); - m_sum += value; - } - } - } - virtual void outputAC(int mcu, int block, int scan, int value){}; - virtual void outputMARK(uint8_t c){ - if (c == 0xd9) { // EOI - if(m_sum == 0) { - x_center = y_center = -1; // not found - } else { - x_center = m_x_sum / m_sum; - y_center = m_y_sum / m_sum; - } - m_x_sum = m_y_sum = m_sum = 0; // reset - EOI_count++; - led3 = !led3; - } - }; -}; - -CalcCenter* calc = NULL; -void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) -{ - if (calc) { - calc->input(buf+12, len-12); - } - if (buf[1]&1) { // FID - led1 = !led1; - } -} - -BaseUsbHost *UsbHost; -UsbHub* hub; -ControlEp* ctlEp = NULL; -LogitechC270* cam; - -void display_thread(void const *args) { - Timer t; - term.cls(); - int fg, old_fg = 0xffffff; - while(1) { - int y; - for(y = 0; y < HEIGHT/8; y++) { - term.locate(0, y); - for(int x = 0; x < WIDTH/16; x++) { - int value = calc->m_buf[y*WIDTH/16+x]; - if (value >= THRESHOLD) { - fg = 0xff0000; // red - } else { - fg = 0xffffff; // white - } - if (fg != old_fg) { - term.foreground(fg); - old_fg = fg; - } - term.printf("%+4d,", value); - } - } - term.locate(0, y); - term.printf("Cr:(%d,%d)[width=%d height=%d yblock=%d %u]\n", - calc->x_center, calc->y_center, calc->width, calc->height, calc->yblock, calc->EOI_count); - term.printf("[CC:"); - for(int i = 0; i < 16; i++) { - term.printf(" %u", cam->report_cc_count[i]); - } - term.printf("]\n"); - term.printf("[PS:"); - for(int i = 0; i < 16; i++) { - term.printf(" %u", cam->report_ps_cc_count[i]); - } - term.printf("]\n"); - Thread::wait(200); - //Thread::signal_wait(1, 2000); - led2 = !led2; - } -} - -int main() { - term.baud(921600); - term.printf("%s\n", __FILE__); - - calc = new CalcCenter; - TEST_ASSERT(calc); - - UsbHost = new BaseUsbHost; - TEST_ASSERT_TRUE(UsbHost); - - UsbHub* hub = new UsbHub(); - TEST_ASSERT_TRUE(hub); - - for(int i = 0; i < MAX_HUB_PORT; i++) { - if (LogitechC270::check(hub->PortEp[i])) { - ctlEp = hub->PortEp[i]; - break; - } - } - if (ctlEp == NULL) { - error("LogitechC270 not found\n"); - } - - cam = new LogitechC270(C270_160x120, _15FPS, ctlEp); - TEST_ASSERT_TRUE(cam); - cam->setOnResult(callback_motion_jpeg); - - Thread thread(display_thread, NULL, osPriorityBelowNormal); - - while(1) { - cam->poll(); - } -} -#endif
--- a/example1_UsbFlashDrive.cpp Wed Dec 05 13:25:18 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -#if 0 -#include "mbed.h" -#include "rtos.h" -#include "BaseUsbHost.h" -#define DEBUG -#include "BaseUsbHostDebug.h" -#define TEST -#include "BaseUsbHostTest.h" -#include "UsbFlashDrive.h" - -DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); -Serial pc(USBTX, USBRX); - -BaseUsbHost *UsbHost; -UsbHub* hub; -ControlEp* ctlEp = NULL; -UsbFlashDrive* drive; -int main() { - pc.baud(921600); - printf("%s\n", __FILE__); - - UsbHost = new BaseUsbHost; - TEST_ASSERT_TRUE(UsbHost); - - UsbHub* hub = new UsbHub(); - TEST_ASSERT_TRUE(hub); - - for(int i = 0; i < MAX_HUB_PORT; i++) { - if (UsbFlashDrive::check(hub->PortEp[i])) { - ctlEp = hub->PortEp[i]; - break; - } - } - if (ctlEp == NULL) { - error("USB Flash Drive not found\n"); - } - TEST_ASSERT(ctlEp); - - drive = new UsbFlashDrive("usb", ctlEp); - TEST_ASSERT(drive); - - const int size_table[] = { - 1024*1, - 1024*2, - 1024*4, - 1024*8, - 1024*16, - 1024*32, - 1024*64, - 1024*128, - 1204*256, - 1204*512, - }; - - printf("USB FLASH DRIVE read/write test\n"); - - char path[32]; - int size; - Timer t; - for(int n = 0; n <= 9; n++) { - int file_size = size_table[n]; - sprintf(path, "/usb/test%d.txt", n); - FILE* fp = fopen(path, "wb"); - size = 0; - t.reset(); - t.start(); - if (fp) { - for(int i = 0; i < file_size; i++) { - int c = i & 0xff; - fputc(c, fp); - size++; - } - t.stop(); - fclose(fp); - } - printf("write file %d bytes %d ms %s\n", size, t.read_ms(), path); - led1 = !led1; - } - - for(int n = 0; n <=9; n++) { - sprintf(path, "/usb/test%d.txt", n); - FILE* fp = fopen(path, "rb"); - size = 0; - t.reset(); - t.start(); - if (fp) { - while(1) { - int c = fgetc(fp); - if (c == EOF) { - break; - } - size++; - } - t.stop(); - fclose(fp); - } - printf("read file %d bytes %d ms %s\n", size, t.read_ms(), path); - led2 = !led2; - } - - exit(1); -} - -#endif
--- a/example1_UsbMouseHost.cpp Wed Dec 05 13:25:18 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -#if 0 -#include "mbed.h" -#include "rtos.h" -#include "BaseUsbHost.h" -#define DEBUG -#include "BaseUsbHostDebug.h" -#define TEST -#include "BaseUsbHostTest.h" -#include "UsbMouseHost.h" - -Serial pc(USBTX, USBRX); -DigitalOut led1(LED1); - -BaseUsbHost *UsbHost; -UsbHub* hub; -ControlEp* ctlEp = NULL; -UsbMouseHost* mouse; -int main() { - pc.baud(921600); - printf("%s\n", __FILE__); - - UsbHost = new BaseUsbHost; - TEST_ASSERT_TRUE(UsbHost); - - UsbHub* hub = new UsbHub(); - TEST_ASSERT_TRUE(hub); - - for(int i = 0; i < MAX_HUB_PORT; i++) { - if (UsbMouseHost::check(hub->PortEp[i])) { - ctlEp = hub->PortEp[i]; - break; - } - } - if (ctlEp == NULL) { - error("USB Mouse not found\n"); - } - - mouse = new UsbMouseHost(ctlEp); - TEST_ASSERT(mouse); - - while(1) { - uint32_t status; - int r = mouse->read(&status); - if (r == USB_OK) { - printf("%08X\n", status); - if (status & 1) { // left - led1 = !led1; - } else if (status & 2) { // right - break; - } - } - } - exit(1); -} - -#endif
--- a/example2_LifeCamVX700.cpp Wed Dec 05 13:25:18 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -#if 0 -// example2_LifeCamVX700.cpp -#include "mbed.h" -#include "rtos.h" -#include "BaseUsbHost.h" -#define DEBUG -#include "BaseUsbHostDebug.h" -#define TEST -#include "BaseUsbHostTest.h" -#include "LifeCamVX700.h" -#include "BaseJpegDecode.h" -#include "Terminal.h" - -// LifeCamVX700 -#define WIDTH 160 -#define HEIGHT 120 - -#define THRESHOLD 200 - -DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); -Terminal term(USBTX, USBRX); - -class JpegDecode : public BaseJpegDecode { -public: - uint32_t EOI_count; - int8_t m_buf[WIDTH/8*HEIGHT/8]; - bool mode_CbCr; - JpegDecode() { - mode_CbCr = false; - EOI_count = 0; - memset(m_buf, 0, sizeof(m_buf)); - } - virtual void outputDC(int mcu, int block, int value) { - if (mcu >= (WIDTH/16*HEIGHT/8)) { - return; - } - if (mode_CbCr) { - if (block == 2 || block == 3) { - value *= qt[1][0]; - value /= 16; - m_buf[mcu*2+block-2] = value; - } - } else { - if (block == 0 || block == 1) { - value *= qt[0][0]; - value /= 16; - m_buf[mcu*2+block] = value; - } - } - } - virtual void outputAC(int mcu, int block, int scan, int value){}; - virtual void outputMARK(uint8_t c){ - if (c == 0xd9) { // EOI - EOI_count++; - led3 = !led3; - } - }; -}; - -JpegDecode* decode = NULL; -void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) -{ - if (decode) { - decode->input(buf+12, len-12); - } - if (buf[1]&1) { // FID - led1 = !led1; - } -} - -BaseUsbHost *UsbHost; -UsbHub* hub; -ControlEp* ctlEp = NULL; -LifeCamVX700* cam; - -void display_thread(void const *args) { - term.cls(); - int n = 0; - while(1) { - int y; - for(y = 0; y < HEIGHT/8; y++) { - term.locate(0, y); - for(int x = 0; x < WIDTH/8; x++) { - int value = decode->m_buf[y*WIDTH/8+x]; - term.printf("%+3d,", value); - } - } - term.locate(0, y); - term.printf("[%s width=%d height=%d yblock=%d %u]\n", decode->mode_CbCr ? "CbCr": "Y0Y1", - decode->width, decode->height, decode->yblock, decode->EOI_count); - term.printf("[CC:"); - for(int i = 0; i < 16; i++) { - term.printf(" %u", cam->report_cc_count[i]); - } - term.printf("]\n"); - term.printf("[PS:"); - for(int i = 0; i < 16; i++) { - term.printf(" %u", cam->report_ps_cc_count[i]); - } - term.printf("]\n"); - Thread::wait(200); - //Thread::signal_wait(1, 2000); - led2 = !led2; - if (n++ > (20000/200)) { - n = 0; - decode->mode_CbCr = !decode->mode_CbCr; - } - } -} - -int main() { - term.baud(921600); - term.printf("%s\n", __FILE__); - - decode = new JpegDecode; - TEST_ASSERT(decode); - - UsbHost = new BaseUsbHost; - TEST_ASSERT_TRUE(UsbHost); - - UsbHub* hub = new UsbHub(); - TEST_ASSERT_TRUE(hub); - - for(int i = 0; i < MAX_HUB_PORT; i++) { - if (LifeCamVX700::check(hub->PortEp[i])) { - ctlEp = hub->PortEp[i]; - break; - } - } - if (ctlEp == NULL) { - error("LifeCamVX700 not found\n"); - } - - cam = new LifeCamVX700(VX700_160x120, _5FPS, ctlEp); - TEST_ASSERT_TRUE(cam); - cam->setOnResult(callback_motion_jpeg); - - Thread thread(display_thread, NULL, osPriorityBelowNormal); - - while(1) { - cam->poll(); - } -} -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example2_LogitechC270.cpp Tue Dec 11 15:28:00 2012 +0000 @@ -0,0 +1,178 @@ +#if 1 +// example2_LogitechC270.cpp +// +// simple color tracking +// +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +#include "LogitechC270.h" +#include "UvcCam.h" +#include "BaseJpegDecode.h" +#include "Terminal.h" +#include "MyThread.h" + +// Logitech C270 +#define WIDTH 160 +#define HEIGHT 120 + +#define THRESHOLD 200 + +DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); +Terminal term(USBTX, USBRX); + +class CalcCenter : public MyThread, public BaseJpegDecode { +public: + int y_center, x_center; + int m_x_sum, m_y_sum, m_sum; + uint32_t EOI_count; + int16_t buf_Cb[WIDTH/16*HEIGHT/8]; // debug + int16_t buf_Cr[WIDTH/16*HEIGHT/8]; // debug + CalcCenter(BaseUvc* cam) { + m_cam = cam; + m_cam->setOnResult(this, &CalcCenter::callback_motion_jpeg); + EOI_count = 0; + } +protected: + void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) { + input(buf+12, len-12); + if (buf[1]&1) { // FID + led1 = !led1; + } + } + + virtual void outputDC(int mcu, int block, int value) { + if (mcu >= (WIDTH/16*HEIGHT/8)) { + return; + } + if (block == 2) { + buf_Cb[mcu] = value * qt[1][0]; + } else if (block == 3) { // 0-1:Y 2:Cb 3:Cr + buf_Cr[mcu] = value * qt[1][0]; + value *= qt[1][0]; + if (value >= THRESHOLD) { // red + m_x_sum += value*(mcu%(WIDTH/16)); + m_y_sum += value*(mcu/(WIDTH/16)); + m_sum += value; + } + } + } + virtual void outputAC(int mcu, int block, int scan, int value){}; + virtual void outputMARK(uint8_t c){ + if (c == 0xd9) { // EOI + if(m_sum == 0) { + x_center = y_center = -1; // not found + } else { + x_center = m_x_sum / m_sum; + y_center = m_y_sum / m_sum; + } + m_x_sum = m_y_sum = m_sum = 0; // reset + EOI_count++; + led3 = !led3; + } + } + + virtual void run() { + while(true) { + if (m_cam) { + m_cam->poll(); + } + } + } + BaseUvc* m_cam; +}; + +BaseUvc* cam = NULL; +CalcCenter* calc = NULL; + +#define PI 3.14159265 + +class display_Thread : public MyThread { + virtual void run() { + term.cls(); + int fg, old_fg = 0xffffff; + while(1) { + int column = 0; + for(int y = 0; y < HEIGHT/8; y++) { + term.locate(0, column++); + for(int x = 0; x < WIDTH/16; x++) { + int value = calc->buf_Cr[y*WIDTH/16+x]; + if (value >= THRESHOLD) { + fg = 0xff0000; // red + } else { + fg = 0xffffff; // white + } + if (fg != old_fg) { + term.foreground(fg); + old_fg = fg; + } + term.printf("%+4d,", value); + } + } + term.locate(0, column++); + term.printf("Cr:(%d,%d)", calc->x_center, calc->y_center); +#if 0 + for(int y = 0; y < HEIGHT/8; y++) { + term.locate(0, column++); + for(int x = 0; x < WIDTH/16; x++) { + float Cb = calc->buf_Cb[y*WIDTH/16+x]; + float Cr = calc->buf_Cr[y*WIDTH/16+x]; + float value; + if (Cb == 0.0) { + value = 0.0; + } else { + value = (atan(Cr / Cb) + PI/2.0)* 360.0 / PI; + } + term.printf("%3.0f,", value); + } + } +#endif + term.locate(0, column++); + term.printf("width=%d height=%d yblock=%d EOI: %u]\n", + calc->width, calc->height, calc->yblock, calc->EOI_count); + term.printf("CC:"); + for(int i = 0; i < 16; i++) { + term.printf(" %u", cam->report_cc_count[i]); + } + term.printf("]\n"); + term.printf("PS:"); + for(int i = 0; i < 16; i++) { + term.printf(" %u", cam->report_ps_cc_count[i]); + } + term.printf("]\n"); + Thread::wait(200); + led2 = !led2; + } + } +}; + +int main() { + term.baud(921600); + term.printf("%s\n", __FILE__); + + BaseUsbHost* UsbHost = new BaseUsbHost; + UsbHub* hub = new UsbHub(); + + for(int port = 1; port <= MAX_HUB_PORT; port++) { + ControlEp* ctlEp = hub->GetPortEp(port); + if (LogitechC270::check(ctlEp)) { + cam = new LogitechC270(C270_160x120, _10FPS, ctlEp); + break; + } + if (UvcCam::check(ctlEp)) { + cam = new UvcCam(UVC_MJPEG, UVC_160x120, _10FPS, ctlEp); + break; + } + } + if (cam == NULL) { + error("USB camera not found\n"); + } + calc = new CalcCenter(cam); + calc->start(); + + display_Thread* th = new display_Thread; + th->start(osPriorityBelowNormal); + + Thread::wait(osWaitForever); +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example_captureJPEG.cpp Tue Dec 11 15:28:00 2012 +0000 @@ -0,0 +1,140 @@ +#if 0 +// example_captureJPEG.cpp +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +#include "LogitechC270.h" +#include "UvcCam.h" +#include "UsbFlashDrive.h" +#include "decodeMJPEG.h" +#include "MyThread.h" + +#define IMAGE_BUF_SIZE (1024*8) +#define INTERVAL_S 10 +#define SHOT_N 5 +#define BASE_PATH "usb" + +Serial pc(USBTX, USBRX); +DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); + +class captureJPEG : public MyThread, public decodeMJPEG { +public: + captureJPEG(BaseUvc* cam) { + m_cam = cam; + m_cam->setOnResult(this, &captureJPEG::callback_motion_jpeg); + interval_t.start(); + shot = 0; + for(buf_size = IMAGE_BUF_SIZE; ; buf_size -= 128) { + buf = new uint8_t[buf_size]; + if (buf) { + break; + } + } + printf("%p buf size: %d\n", buf, buf_size); + } + int shot; + Timer interval_t; +protected: + virtual void outputJPEG(uint8_t c, int status) { + if (status == JPEG_START) { + pos = 0; + led2 = !led2; + } + if (pos < buf_size) { + buf[pos++] = c; + } + if (status == JPEG_END) { + led3 = !led3; + if (interval_t.read_ms() > INTERVAL_S*1000) { + interval_t.reset(); + led4 = !led4; + if (shot < SHOT_N) { + char path[32]; + snprintf(path, sizeof(path), "/%s/image%02d.jpg", BASE_PATH, shot); + printf("%d %s %d bytes\n", shot, path, pos); + FILE* fp = fopen(path, "wb"); + if (fp) { + fwrite(buf, pos, 1, fp); + fclose(fp); + } + shot++; + } + } + } + } + + void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) { + inputPacket(buf, len); + if (buf[1]&1) { // FID + led1 = !led1; + } + if (buf[1]&2) { // EOF + led2 = !led2; + } + } + + virtual void run() { + while(true) { + if (m_cam) { + m_cam->poll(); + } + } + } + uint8_t* buf; + int buf_size; + int pos; + BaseUvc* m_cam; +}; + +int main() { + pc.baud(921600); + printf("%s\n", __FILE__); + + BaseUvc* cam = NULL; + UsbFlashDrive* drive = NULL; + BaseUsbHost* usbHost = new BaseUsbHost(); + UsbHub* hub = new UsbHub(); + + for(int i = 1; i <= MAX_HUB_PORT; i++) { + ControlEp* ctlEp = hub->GetPortEp(i); + if (drive == NULL && UsbFlashDrive::check(ctlEp)) { + drive = new UsbFlashDrive("usb", ctlEp); + } + if (cam == NULL && LogitechC270::check(ctlEp)) { + cam = new LogitechC270(C270_160x120, _5FPS, ctlEp); + } + if (cam == NULL && UvcCam::check(ctlEp)) { + cam = new UvcCam(UVC_MJPEG, UVC_160x120, _5FPS, ctlEp); + } + } + if (cam == NULL) { + error("UVC cam not found\n"); + } + if (drive == NULL) { + error("USB flash drive not found\n"); + } + + captureJPEG* capture = new captureJPEG(cam); + printf("captureJPEG: %p %d\n", capture, sizeof(captureJPEG)); + capture->set_stack(DEFAULT_STACK_SIZE+256); + capture->start(); + + for(int n = 0; ; n++) { + printf("%d captureJPEG stack used: %d/%d bytes, interval %d/%d %d/%d sec\n", + n, capture->stack_used(), capture->stack_size(), + capture->shot, SHOT_N, capture->interval_t.read_ms()/1000, INTERVAL_S); + printf("CC:"); + for(int i = 0; i < 16; i++) { + printf(" %u", cam->report_cc_count[i]); + } + printf("\n"); + printf("PS:"); + for(int i = 0; i < 16; i++) { + printf(" %u", cam->report_ps_cc_count[i]); + } + printf("\n"); + Thread::wait(3000); + } +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example_captureYUY2.cpp Tue Dec 11 15:28:00 2012 +0000 @@ -0,0 +1,125 @@ +#if 0 +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +#include "UvcCam.h" +#include "MyThread.h" +#include <bitset> + +Serial pc(USBTX, USBRX); +DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); + +class decodeYUY2 { +public: + decodeYUY2() { + xy = 0; + } +protected: + void inputPacket(uint8_t* buf, int len) { + for(int i = 12; i < len; i += 4) { + outputY(xy, buf[i]); + outputCb(xy+1, buf[i+1]); + outputY(xy+2, buf[i+2]); + outputCr(xy+3, buf[i+3]); + xy += 4; + } + if (buf[1]&2) { //EOF + xy = 0; + } + } + virtual void outputY(int xy, uint8_t c)=0; + virtual void outputCb(int xy, uint8_t c)=0; + virtual void outputCr(int xy, uint8_t c)=0; + int xy; +}; + +class captureYUY2 : public MyThread, public decodeYUY2 { +public: + captureYUY2(BaseUvc* cam) { + m_cam = cam; + m_cam->setOnResult(this, &captureYUY2::callback); + } + bitset<160*120> bitmap; + uint8_t buf[160]; +protected: + virtual void outputY(int xy, uint8_t c) { + if (xy < bitmap.size()) { + bitmap.set(xy, c > 0x80); + } + if (xy < sizeof(buf)) { + buf[xy] = c; + } + } + virtual void outputCb(int xy, uint8_t c) {} + virtual void outputCr(int xy, uint8_t c) {} + void callback(uint16_t frame, uint8_t* buf, int len) { + inputPacket(buf, len); + if (buf[1]&1) { // FID + led1 = !led1; + } + if (buf[1]&2) { // EOF + led2 = !led2; + } + } + virtual void run() { + while(true) { + if (m_cam) { + m_cam->poll(); + } + } + } + BaseUvc* m_cam; +}; + +int main() { + pc.baud(921600); + printf("%s\n", __FILE__); + + BaseUsbHost* usbHost = new BaseUsbHost(); + UsbHub* hub = new UsbHub(); + BaseUvc* cam = NULL; + for(int i = 1; i <= MAX_HUB_PORT; i++) { + ControlEp* ctlEp = hub->GetPortEp(i); + if (cam == NULL && UvcCam::check(ctlEp)) { + cam = new UvcCam(UVC_YUY2, UVC_160x120, _5FPS, ctlEp); + } + } + if (cam == NULL) { + error("cam not found\n"); + } + captureYUY2* capture = new captureYUY2(cam); + capture->set_stack(DEFAULT_STACK_SIZE-128*12); + capture->start(); + + for(int n = 0; ; n++) { + for(int y = 0; y < 120; y+= 6) { + for(int x = 0; x < 160; x+= 3) { + printf("%c", capture->bitmap[y*160+x] ? '*':'.'); + } + printf("\n"); + } + + printf("%d captureYUY2 stack used: %d/%d bytes\n", n, capture->stack_used(), capture->stack_size()); + printf("CC:"); // conditon code + for(int i = 0; i < 16; i++) { + printf(" %u", cam->report_cc_count[i]); + } + printf("\n"); + printf("PS:"); // Packet status + for(int i = 0; i < 16; i++) { + printf(" %u", cam->report_ps_cc_count[i]); + } + printf("\n"); + + for(int i = 0; i < 64; i++) { + printf("%02X ", capture->buf[i]); + if (i%16==15) { + printf("\n"); + } + } + Thread::wait(400); + led3 = !led3; + } +} + +#endif
--- a/mbed.bld Wed Dec 05 13:25:18 2012 +0000 +++ b/mbed.bld Tue Dec 11 15:28:00 2012 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/mbed_official/code/mbed/builds/b60934f96c0c \ No newline at end of file +http://mbed.org/users/mbed_official/code/mbed/builds/63cdd78b2dc1 \ No newline at end of file