BaseJpegDeocde exampe program
Dependencies: BaseJpegDecode Terminal BaseUsbHost mbed mbed-rtos
Fork of BaseJpegDecode by
Revision 7:3ad9c948bc06, committed 2013-01-27
- Comitter:
- va009039
- Date:
- Sun Jan 27 11:15:26 2013 +0000
- Parent:
- 6:95be1cd2bc14
- Commit message:
- change library uvchost to BaseUsbHost, delete SimpleJpegDecode
Changed in this revision
--- a/BaseJpegDecode.lib Wed Dec 05 12:41:25 2012 +0000 +++ b/BaseJpegDecode.lib Sun Jan 27 11:15:26 2013 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/va009039/code/BaseJpegDecode/#e243fa781e5c +http://mbed.org/users/va009039/code/BaseJpegDecode/#85e99ec2e7b5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BaseUsbHost.lib Sun Jan 27 11:15:26 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/va009039/code/BaseUsbHost/#d931d24c2f81
--- a/FATFileSystem.lib Wed Dec 05 12:41:25 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/mbed_official/code/FATFileSystem/#b6669c987c8e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyThread/MyThread.h Sun Jan 27 11:15:26 2013 +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
--- a/SimpleJpegDecode.cpp Wed Dec 05 12:41:25 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -#include "SimpleJpegDecode.h" - -#define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0); -#define ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; - - -#define _1_4020 45 -#define _0_3441 11 -#define _0_7139 23 -#define _1_7718 57 -#define _0_0012 0 - -int adjust(int r) { - if (r >= 0) { - if (r <= 255) { - return r; - } else { - return 255; - } - } else { - return 0; - } -} - -void convYUVtoRGB(uint8_t rgb[], int y, int u, int v) -{ - rgb[0] = adjust((y*32 + v*_1_4020)/32 + 128); - rgb[1] = adjust((y*32 - u*_0_3441 - v*_0_7139)/32 + 128); - rgb[2] = adjust((y*32 + u*_1_7718 - v*_0_0012)/32 + 128); -} - -SimpleJpegDecode::SimpleJpegDecode(uint8_t output_mode) -{ - m_output_mode = output_mode; - clearOnResult(); -} - - -void SimpleJpegDecode::output(int mcu, int block, int scan, int value) -{ - int sc = (block < yblock) ? 0 : 1; - inputBLOCK(mcu, block, scan, value * qt[sc][scan]); -} - -void SimpleJpegDecode::outputDC(int mcu, int block, int value) -{ - output(mcu, block, 0, value); - DC_count++; -} - -void SimpleJpegDecode::outputAC(int mcu, int block, int scan, int value) -{ - output(mcu, block, scan, value); - AC_count++; -} - -void SimpleJpegDecode::outputMARK(uint8_t c) -{ -} - -void SimpleJpegDecode::format_YUV(int mcu, int block, int8_t* values) -{ - if (block < yblock+1) { - memcpy(m_block_data[block], values, 64); - return; - } - int mcu_x_count = (width+15)/16; - int mcu_x = mcu % mcu_x_count; - int mcu_y = mcu / mcu_x_count; - uint8_t yuv[3]; - if (yblock == 2) { - for(int y = 0; y < 8; y++) { - for(int x = 0; x < 16; x++) { - yuv[0] = m_block_data[x/8][y*8+x%8] + 128; - yuv[1] = m_block_data[2][y*8+x/2] + 128; - yuv[2] = values[y*8+x/2] + 128; - onResult(mcu_x * 16 + x, mcu_y * 8 + y, yuv); - } - } - } else if (yblock == 4) { - for(int y = 0; y < 16; y++) { - for(int x = 0; x < 16; x++) { - yuv[0] = m_block_data[(y/8)*2+x/8][(y%8)*8+x%8] + 128; - yuv[1] = m_block_data[4][(y/2)*8+x/2] + 128; - yuv[2] = values[(y/2)*8+x/2] + 128; - onResult(mcu_x * 16 + x, mcu_y * 16 + y, yuv); - } - } - } else { - ASSERT(yblock == 2 || yblock == 4); - } -} - -void SimpleJpegDecode::format_RGB24(int mcu, int block, int8_t* values) -{ - if (block < yblock+1) { - memcpy(m_block_data[block], values, 64); - return; - } - int mcu_x_count = (width+15)/16; - int mcu_x = mcu % mcu_x_count; - int mcu_y = mcu / mcu_x_count; - uint8_t rgb[3]; - if (yblock == 2) { - for(int y = 0; y < 8; y++) { - for(int x = 0; x < 16; x++) { - int8_t yuv_y = m_block_data[x/8][y*8+x%8]; - int8_t yuv_u = m_block_data[2][y*8+x/2]; - int8_t yuv_v = values[y*8+x/2]; - convYUVtoRGB(rgb, yuv_y, yuv_u, yuv_v); - onResult(mcu_x * 16 + x, mcu_y * 8 + y, rgb); - } - } - } else if (yblock == 4) { - for(int y = 0; y < 16; y++) { - for(int x = 0; x < 16; x++) { - int8_t yuv_y = m_block_data[(y/8)*2+x/8][(y%8)*8+x%8]; - int8_t yuv_u = m_block_data[4][(y/2)*8+x/2]; - int8_t yuv_v = values[(y/2)*8+x/2]; - convYUVtoRGB(rgb, yuv_y, yuv_u, yuv_v); - onResult(mcu_x * 16 + x, mcu_y * 16 + y, rgb); - } - } - } else { - ASSERT(yblock == 2 || yblock == 4); - } -} - -void SimpleJpegDecode::outputBLOCK(int mcu, int block, int8_t* values) -{ - BLOCK_count++; - if (m_output_mode == YUV) { - format_YUV(mcu, block, values); - } else if (m_output_mode == RGB24) { - format_RGB24(mcu, block, values); - } else { - ASSERT(m_output_mode == YUV || m_output_mode == RGB24); - } -} - -void SimpleJpegDecode::onResult(int x, int y, uint8_t* yuv) -{ - if(m_pCbItem && m_pCbMeth) - (m_pCbItem->*m_pCbMeth)(x, y, yuv); - else if(m_pCb) - m_pCb(x, y, yuv); -} - -void SimpleJpegDecode::setOnResult( void (*pMethod)(int, int, uint8_t*) ) -{ - m_pCb = pMethod; - m_pCbItem = NULL; - m_pCbMeth = NULL; -} - -void SimpleJpegDecode::clearOnResult() -{ - m_pCb = NULL; - m_pCbItem = NULL; - m_pCbMeth = NULL; -}
--- a/SimpleJpegDecode.h Wed Dec 05 12:41:25 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -#ifndef SIMPLE_JPEG_DECODE_H -#define SIMPLE_JPEG_DECODE_H - -#include "BaseJpegDecode.h" -#include "inverseDCT.h" - -#define YUV 0 -#define RGB24 1 - -class SimpleJpegDecode : public BaseJpegDecode, public inverseDCT { -public: - SimpleJpegDecode(uint8_t output_mode=RGB24); - - void format_YUV(int mcu, int block, int8_t* values); - void format_RGB24(int mcu, int block, int8_t* values); - - void output(int mcu, int block, int scan, int value); - virtual void outputDC(int mcu, int block, int value); - virtual void outputAC(int mcu, int block, int scan, int value); - virtual void outputMARK(uint8_t c); - virtual void outputBLOCK(int muc, int block, int8_t* values); // iDCT - - int8_t m_block_data[5][64]; - int DC_count; - int AC_count; - int BLOCK_count; - - ///Setups the result callback - /** - @param pMethod : callback function - */ - void setOnResult( void (*pMethod)(int, int, uint8_t*) ); - - ///Setups the result callback - /** - @param pItem : instance of class on which to execute the callback method - @param pMethod : callback method - */ - class CDummy; - template<class T> - void setOnResult( T* pItem, void (T::*pMethod)(int, int, uint8_t*) ) - { - m_pCb = NULL; - m_pCbItem = (CDummy*) pItem; - m_pCbMeth = (void (CDummy::*)(int, int, uint8_t*)) pMethod; - } - void clearOnResult(); -protected: - void onResult(int x, int y, uint8_t* yuv); - CDummy* m_pCbItem; - void (CDummy::*m_pCbMeth)(int, int, uint8_t*); - void (*m_pCb)(int, int, uint8_t*); - uint8_t m_output_mode; -}; - -#endif // SIMPLE_JPEG_DECODE_H \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UvcCam/UvcCam.cpp Sun Jan 27 11:15:26 2013 +0000 @@ -0,0 +1,566 @@ +// UvcCam.cpp 2013/1/25 +#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 Sun Jan 27 11:15:26 2013 +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
--- a/bmp24.h Wed Dec 05 12:41:25 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -#ifndef BMP24_H -#define BMP24_H - -#define BMP24_WIDTH (16*4) -#define BMP24_HEIGHT (16*3) - -class bmp24 { -public: - int width; - int height; - - bmp24() { - width = BMP24_WIDTH; - height = BMP24_HEIGHT; - } - - void clear() { - memset(m_bitmap, 0, sizeof(m_bitmap)); - } - - void point(int x, int y, uint8_t* rgb) { - if (x >= 0 && x < width && y >= 0 && y < height) { - int pos = y*width*3+x*3; - m_bitmap[pos++] = rgb[0]; - m_bitmap[pos++] = rgb[1]; - m_bitmap[pos] = rgb[2]; - } - } - - void LE32write(uint8_t* buf, int value) { - *buf++ = value & 0xff; - *buf++ = (value>>8) & 0xff; - *buf++ = (value>>16) & 0xff; - *buf = (value>>24) & 0xff; - } - - void writeFile(const char *path) { - FILE *fp = fopen(path, "wb"); - if (fp == NULL) { - return; - } - uint8_t header[] = { -0x42,0x4d,0x36,0xe1,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00, -0x00,0x00,0xa0,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00}; - int file_size = sizeof(header) + sizeof(m_bitmap); - LE32write(header+2, file_size); - LE32write(header+18, width); - LE32write(header+22, height); - - fwrite(header, 1, sizeof(header), fp); - for(int y = height-1; y >=0; y--) { - for(int x = 0; x < width; x++) { - fputc(m_bitmap[y*width*3+x*3+2], fp); - fputc(m_bitmap[y*width*3+x*3+1], fp); - fputc(m_bitmap[y*width*3+x*3+0], fp); - } - } - fclose(fp); - } - - uint8_t m_bitmap[BMP24_WIDTH*BMP24_HEIGHT*3]; -}; - -#endif // BMP24_H
--- a/example1_c270.cpp Wed Dec 05 12:41:25 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -#if 1 -// -// simple color tracking -// -#include "mbed.h" -#include "BaseJpegDecode.h" -#include "uvc.h" -#include "Terminal.h" - -// Logitech C270 -#define WIDTH 320 -//#define HEIGHT 176 - -// LifeCam -#define HEIGHT 240 - -#define THRESHOLD 100 - -#define ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; - -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; - int16_t m_buf[WIDTH/16*HEIGHT/8]; - 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]; - ASSERT(value < 32367 && value > -32368); - 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 - led2 = !led2; - } - }; -}; - -CalcCenter* calc = NULL; - -void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) -{ - if (calc) { - calc->input(buf+12, len-12); - } - led1 = buf[1]&1; // FID -} - -int main() { - term.baud(921600); - term.printf("%s\n", __FILE__); - - calc = new CalcCenter; - ASSERT(calc); - uvc* cam = new uvc; - ASSERT(cam); - cam->SetImageSize(WIDTH, HEIGHT); - cam->SetFrameInterval(2000000); // 5.0fps - cam->setOnResult(callback_motion_jpeg); - ASSERT(cam->setup() >= 0); - 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); - cam->poll(); - } - } - term.locate(0, y); - term.printf("Cr:(%d,%d)", calc->x_center, calc->y_center); - cam->wait_ms(500); - led3 = !led3; - } -} -#endif
--- a/example_SimpleJpegDecode.cpp Wed Dec 05 12:41:25 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -#if 0 -// -// split jpeg to bmp files -// -#include "mbed.h" -#include "SimpleJpegDecode.h" -#include "bmp24.h" -#include "uvc.h" -#include "msc.h" - -#define ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; - -DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); -Serial pc(USBTX, USBRX); - -SimpleJpegDecode* decode = NULL; -bmp24* bmp = NULL; - -int offset_x = 0; -int offset_y = 0; - -void callbackRGB(int x, int y, uint8_t* rgb) -{ - led1 = !led1; - if (bmp) { - bmp->point(x - offset_x, y - offset_y, rgb); - } -} - -int main() { - pc.baud(921600); - printf("%s\n", __FILE__); - - msc* usb = new msc("usb"); - int r = usb->setup(); - ASSERT(r == 0); - - bmp = new bmp24; - ASSERT(bmp); - - decode = new SimpleJpegDecode(); - ASSERT(decode); - - const char* input_file = "/usb/input.jpg"; - - FILE *fp = fopen(input_file, "rb"); - ASSERT(fp != NULL); - Timer benchmark_t; - benchmark_t.reset(); - benchmark_t.start(); - while(!feof(fp)) { - int c = fgetc(fp); - led2 = !led2; - } - benchmark_t.stop(); - fclose(fp); - printf("input: %s, %d ms\n", input_file, benchmark_t.read_ms()); - - decode->clear(); - fp = fopen(input_file, "rb"); - ASSERT(fp != NULL); - benchmark_t.reset(); - benchmark_t.start(); - while(!feof(fp)) { - int c = fgetc(fp); - decode->input(c); - led2 = !led2; - } - benchmark_t.stop(); - fclose(fp); - printf("width: %d, height: %d, yblock: %d, %d ms\n", decode->width, decode->height, - decode->yblock, benchmark_t.read_ms()); - - decode->setOnResult(callbackRGB); - int n = 0; - for(offset_y = 0; offset_y < decode->height; offset_y += bmp->height) { - for(offset_x = 0; offset_x < decode->width; offset_x += bmp->width) { - bmp->clear(); - decode->clear(); - fp = fopen(input_file, "rb"); - ASSERT(fp != NULL); - benchmark_t.reset(); - benchmark_t.start(); - while(!feof(fp)) { - int c = fgetc(fp); - decode->input(c); - led2 = !led2; - } - benchmark_t.stop(); - fclose(fp); - char path[32]; - sprintf(path, "/usb/output%02d.bmp", n++); - printf("offset: (%3d,%3d), size:(%3d,%3d), %s %d ms\n", - offset_x, offset_y, bmp->width, bmp->height, - path, benchmark_t.read_ms()); - bmp->writeFile(path); - led3 = !led3; - } - led4 = !led4; - } - printf("done\n"); - exit(1); -} -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Jan 27 11:15:26 2013 +0000 @@ -0,0 +1,153 @@ +// BaseJpegDecode_example/main.cpp 2013/1/27 +// simple color tracking +// +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +#include "UvcCam.h" +#include "BaseJpegDecode.h" +#include "Terminal.h" +#include "MyThread.h" + +#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; + +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); + Thread::yield(); + } + } + term.locate(0, column++); + term.printf("Cr:(%d,%d)", calc->x_center, calc->y_center); + + term.locate(0, column++); + term.printf("width=%d height=%d yblock=%d EOI: %u]\nCC:", + calc->width, calc->height, calc->yblock, calc->EOI_count); + for(int i = 0; i < 16; i++) { + term.printf(" %u", cam->report_cc_count[i]); + } + term.printf("]\nPS:"); + for(int i = 0; i < 16; i++) { + term.printf(" %u", cam->report_ps_cc_count[i]); + } + term.printf("]\n"); + Thread::wait(150); + led2 = !led2; + } + } +}; + +void no_memory () { + error("Failed to allocate memory!\n"); +} + +int main() { + term.baud(921600); + term.printf("%s\n", __FILE__); + set_new_handler(no_memory); + + BaseUsbHost* UsbHost = new BaseUsbHost; + ControlEp* ctlEp = new ControlEp; // root hub + if (UsbHub::check(ctlEp)) { // hub? + UsbHub* hub = new UsbHub(ctlEp); + ctlEp = hub->search<UvcCam>(); + } + if (!UvcCam::check(ctlEp)) { + error("UVC camera is not connected\n"); + } + cam = new UvcCam(UVC_MJPEG, UVC_160x120, _15FPS, ctlEp); + calc = new CalcCenter(cam); + calc->start(); + + display_Thread* display_th = new display_Thread; + display_th->start(osPriorityBelowNormal); + + Thread::wait(osWaitForever); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Sun Jan 27 11:15:26 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed-rtos/#88a1a9c26ae3
--- a/mbed.bld Wed Dec 05 12:41:25 2012 +0000 +++ b/mbed.bld Sun Jan 27 11:15:26 2013 +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/0954ebd79f59 \ No newline at end of file
--- a/msc/msc.cpp Wed Dec 05 12:41:25 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,390 +0,0 @@ -#include "msc.h" -//#define __DEBUG -#include "mydbg.h" -#include "Utils.h" - -//#define WRITE_PROTECT - -msc::msc(const char* name, int drive): FATFileSystem(name) -{ - DBG("drive=%d\n", drive); - m_name = name; - m_drive = drive; - DBG_ASSERT(sizeof(CBW) == 31); - DBG_ASSERT(sizeof(CSW) == 13); - m_numBlocks = 0; - m_BlockSize = 0; - m_lun = 0; - m_interface = 0; - m_pDev = NULL; - m_pEpBulkIn = NULL; - m_pEpBulkOut = NULL; -} - -int msc::disk_initialize() -{ - DBG("m_BlockSize=%d\n", m_BlockSize); - if (m_BlockSize != 512) { - return 1; - } - return 0; -} - -int msc::disk_write(const uint8_t *buffer, uint64_t block_number) -{ - DBG("buffer=%p block_number=%d\n", buffer, block_number); - int ret = MS_BulkSend(block_number, 1, (uint8_t*)buffer); - if (ret >= 0) { - return 0; - } - return 1; -} - -int msc::disk_read(uint8_t *buffer, uint64_t block_number) -{ - DBG("buffer=%p block_number=%d\n", buffer, block_number); - int ret = MS_BulkRecv(block_number, 1, (uint8_t*)buffer); - if (ret >= 0) { - return 0; - } - return 1; -} - -int msc::disk_status() -{ - DBG("\n"); - return 0; -} - -int msc::disk_sync() -{ - DBG("\n"); - return 0; -} - -uint64_t msc::disk_sectors() -{ - DBG("m_numBlocks=%d\n", m_numBlocks); - return m_numBlocks; -} - -int msc::setup(int timeout) -{ - for(int i = 0; i < 2; i++) { - m_pDev = m_pHost->getDeviceByClass(0x08, m_drive); // USB Mass Storage Class - if (m_pDev || i > 0) { - break; - } - UsbErr rc = Usb_poll(); - if (rc == USBERR_PROCESSING) { - VERBOSE("%p USBERR_PROCESSING\n", this); - return -1; - } - } - DBG("m_pDev=%p\n", m_pDev); - if (m_pDev == NULL) { - VERBOSE("%p MSC DISK(%d) NOT FOUND\n", this, m_drive); - return -1; - } - DBG_ASSERT(m_pDev); - - ParseConfiguration(); - - GetMaxLUN(); - - int retry = 0; - Timer t; - t.start(); - t.reset(); - while(t.read_ms() < timeout) { - DBG("retry=%d t=%d\n", retry, t.read_ms()); - if (retry > 80) { - return -1; - } - int rc = TestUnitReady(); - DBG("TestUnitReady(): %d\n", rc); - if (rc == USBERR_OK) { - DBG("m_CSW.bCSWStatus: %02X\n", m_CSW.bCSWStatus); - if (m_CSW.bCSWStatus == 0x00) { - break; - } - } - GetSenseInfo(); - retry++; - wait_ms(50); - } - if (t.read_ms() >= timeout) { - return -1; - } - ReadCapacity(); - Inquire(); - return 0; -} -void msc::_test() -{ - ReadCapacity(); - - uint8_t buf[512]; - for(int block = 0; block < m_numBlocks; block++) { - DBG("block=%d\n", block); - disk_read(buf, block); - } - exit(1); -} - -int msc::ParseConfiguration() -{ - UsbErr rc; - uint8_t ConfigDesc[9]; - int index = 0; - DBG_ASSERT(m_pDev); - rc = m_pDev->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, ConfigDesc, sizeof(ConfigDesc)); - DBG_ASSERT(rc == USBERR_OK); - DBG_BYTES("ConfigDescriptor 9bytes", ConfigDesc, sizeof(ConfigDesc)); - DBG_ASSERT(ConfigDesc[0] == 9); - DBG_ASSERT(ConfigDesc[1] == 0x02); - int wTotalLength = *((uint16_t*)&ConfigDesc[2]); - DBG("TotalLength: %d\n", wTotalLength); - int bConfigValue = ConfigDesc[5]; - DBG_ASSERT(bConfigValue == 1); - DBG("ConfigValue: %d\n", bConfigValue); - DBG("MaxPower: %d mA\n", ConfigDesc[8]*2); - - uint8_t* buf = new uint8_t[wTotalLength]; - DBG_ASSERT(buf); - rc = m_pDev->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, wTotalLength); - DBG_ASSERT(rc == USBERR_OK); - DBG_ASSERT(ConfigDesc[1] == 0x02); - for (int pos = 0; pos < wTotalLength; pos += buf[pos]) { - DBG_BYTES("CFG", buf+pos, buf[pos]); - int type = buf[pos+1]; - if (USB_DESCRIPTOR_TYPE_INTERFACE == type) { // 0x04 - DBG("InterfaceNumber: %d\n", buf[pos+2]); - DBG("AlternateSetting: %d\n", buf[pos+3]); - DBG("NumEndpoint: %d\n", buf[pos+4]); - DBG("InterfaceClass: %02X\n", buf[pos+5]); - DBG("InterfaceSubClass: %02X\n", buf[pos+6]); - DBG("InterfaceProtocol: %02X\n", buf[pos+7]); - DBG_ASSERT(buf[pos+6] == 0x06); // SCSI - DBG_ASSERT(buf[pos+7] == 0x50); // bulk only - } - if (USB_DESCRIPTOR_TYPE_ENDPOINT == type) { - DBG_ASSERT(buf[pos] == 7); - uint8_t att = buf[pos+3]; - if (att == 2) { // bulk - uint8_t ep = buf[pos+2]; - bool dir = ep & 0x80; // true=IN - uint16_t size = LE16(buf+pos+4); - DBG("EndpointAddress: %02X\n", ep); - DBG("Attribute: %02X\n", att); - DBG("MaxPacketSize: %d\n", size); - UsbEndpoint* pEp = new UsbEndpoint(m_pDev, ep, dir, USB_BULK, size); - DBG_ASSERT(pEp); - if (dir) { - m_pEpBulkIn = pEp; - } else { - m_pEpBulkOut = pEp; - } - } - } - } - delete[] buf; - DBG_ASSERT(m_pEpBulkIn); - DBG_ASSERT(m_pEpBulkOut); - return 0; -} - -int msc::BulkOnlyMassStorageReset() -{ - DBG_ASSERT(m_pDev); - UsbErr rc = m_pDev->controlReceive(0x21, 0xff, 0x0000, m_interface, NULL, 0); - DBG_ASSERT(rc == USBERR_OK); - return rc; -} - -int msc::GetMaxLUN() -{ - DBG_ASSERT(m_interface == 0); - uint8_t temp[1]; - DBG_ASSERT(m_pDev); - UsbErr rc = m_pDev->controlReceive(0xa1, 0xfe, 0x0000, m_interface, temp, sizeof(temp)); - DBG_ASSERT(rc == USBERR_OK); - DBG_BYTES("GetMaxLUN", temp, sizeof(temp)); - m_MaxLUN = temp[0]; - DBG_ASSERT(m_MaxLUN <= 15); - return rc; -} - - -int msc::TestUnitReady() -{ - const uint8_t cdb[6] = {SCSI_CMD_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00}; - m_CBW.dCBWDataTraansferLength = 0; - m_CBW.bmCBWFlags = 0x00; - CommandTransport(cdb, sizeof(cdb)); - StatusTransport(); - return 0; -} - -int msc::GetSenseInfo() -{ - const uint8_t cdb[6] = {SCSI_CMD_REQUEST_SENSE, 0x00, 0x00, 0x00, 18, 0x00}; - m_CBW.dCBWDataTraansferLength = 18; - m_CBW.bmCBWFlags = 0x80; // data In - CommandTransport(cdb, sizeof(cdb)); - - uint8_t buf[18]; - _bulkRecv(buf, sizeof(buf)); - DBG_HEX(buf, sizeof(buf)); - - StatusTransport(); - DBG_ASSERT(m_CSW.bCSWStatus == 0x00); - return 0; -} - -int msc::ReadCapacity() -{ - const uint8_t cdb[10] = {SCSI_CMD_READ_CAPACITY, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}; - m_CBW.dCBWDataTraansferLength = 8; - m_CBW.bmCBWFlags = 0x80; // data In - CommandTransport(cdb, sizeof(cdb)); - - uint8_t buf[8]; - int rc = _bulkRecv(buf, sizeof(buf)); - DBG_ASSERT(rc >= 0); - DBG_HEX(buf, sizeof(buf)); - - StatusTransport(); - DBG_ASSERT(m_CSW.bCSWStatus == 0x00); - - m_numBlocks = BE32(buf); - m_BlockSize = BE32(buf+4); - DBG("m_numBlocks=%d m_BlockSize=%d\n", m_numBlocks, m_BlockSize); - DBG_ASSERT(m_BlockSize == 512); - DBG_ASSERT(m_numBlocks > 0); - return 0; -} - -int msc::Inquire() -{ - const uint8_t cdb[6] = {SCSI_CMD_INQUIRY, 0x00, 0x00, 0x00, 36, 0x00}; - m_CBW.dCBWDataTraansferLength = 36; - m_CBW.bmCBWFlags = 0x80; // data In - CommandTransport(cdb, sizeof(cdb)); - - uint8_t buf[36]; - _bulkRecv(buf, sizeof(buf)); - DBG_HEX(buf, sizeof(buf)); - - StatusTransport(); - return 0; -} - -int msc::MS_BulkRecv(uint32_t block_number, int num_blocks, uint8_t* user_buffer) -{ - DBG_ASSERT(m_BlockSize == 512); - DBG_ASSERT(num_blocks == 1); - DBG_ASSERT(user_buffer); - uint8_t cdb[10] = {SCSI_CMD_READ_10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}; - BE32(block_number, cdb+2); - BE16(num_blocks, cdb+7); - uint32_t len = m_BlockSize * num_blocks; - DBG_ASSERT(len <= 512); - m_CBW.dCBWDataTraansferLength = len; - m_CBW.bmCBWFlags = 0x80; // data In - CommandTransport(cdb, sizeof(cdb)); - - int ret = _bulkRecv(user_buffer, len); - //DBG_HEX(user_buffer, len); - - StatusTransport(); - DBG_ASSERT(m_CSW.bCSWStatus == 0x00); - return ret; -} - -int msc::MS_BulkSend(uint32_t block_number, int num_blocks, uint8_t* user_buffer) -{ -#ifdef WRITE_PROTECT - return 0; -#else - DBG_ASSERT(num_blocks == 1); - DBG_ASSERT(user_buffer); - uint8_t cdb[10] = {SCSI_CMD_WRITE_10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}; - BE32(block_number, cdb+2); - BE16(num_blocks, cdb+7); - uint32_t len = m_BlockSize * num_blocks; - DBG_ASSERT(len <= 512); - m_CBW.dCBWDataTraansferLength = len; - m_CBW.bmCBWFlags = 0x00; // data Out - CommandTransport(cdb, sizeof(cdb)); - - int ret = _bulkSend(user_buffer, len); - //DBG_HEX(user_buffer, len); - - StatusTransport(); - DBG_ASSERT(m_CSW.bCSWStatus == 0x00); - return ret; -#endif //WRITE_PROTECT -} - -int msc::CommandTransport(const uint8_t* cdb, int size) -{ - DBG_ASSERT(cdb); - DBG_ASSERT(size >= 6); - DBG_ASSERT(size <= 16); - m_CBW.bCBWLUN = m_lun; - m_CBW.bCBWCBLength = size; - memcpy(m_CBW.CBWCB, cdb, size); - - m_CBW.dCBWSignature = 0x43425355; - m_CBW.dCBWTag = m_tag++; - m_CBW.bCBWLUN = 0; - //DBG_HEX((uint8_t*)&m_CBW, sizeof(CBW)); - int rc = _bulkSend((uint8_t*)&m_CBW, sizeof(CBW)); - return rc; -} - -int msc::StatusTransport() -{ - DBG_ASSERT(sizeof(CSW) == 13); - int rc = _bulkRecv((uint8_t*)&m_CSW, sizeof(CSW)); - //DBG_HEX((uint8_t*)&m_CSW, sizeof(CSW)); - DBG_ASSERT(m_CSW.dCSWSignature == 0x53425355); - DBG_ASSERT(m_CSW.dCSWTag == m_CBW.dCBWTag); - DBG_ASSERT(m_CSW.dCSWDataResidue == 0); - return rc; -} - -int msc::_bulkRecv(uint8_t* buf, int size) -{ - UsbErr rc = m_pEpBulkIn->transfer(buf, size); - DBG_ASSERT(rc == USBERR_PROCESSING); - while(m_pEpBulkIn->status() == USBERR_PROCESSING){ - wait_us(1); - } - int ret = m_pEpBulkIn->status(); - if (ret >= 0) { - return ret; - } - DBG("buf=%p size=%d ret=%d\n", buf, size, ret); - return ret; -} - -int msc::_bulkSend(uint8_t* buf, int size) -{ - DBG_ASSERT(m_pEpBulkOut); - UsbErr rc = m_pEpBulkOut->transfer(buf, size); - DBG_ASSERT(rc == USBERR_PROCESSING); - while(m_pEpBulkOut->status() == USBERR_PROCESSING){ - wait_us(1); - } - int ret = m_pEpBulkOut->status(); - if (ret >= 0) { - return ret; - } - DBG("buf=%p size=%d ret=%d\n", buf, size, ret); - return ret; -}
--- a/msc/msc.h Wed Dec 05 12:41:25 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -#ifndef MSC_H -#define MSC_H -#include "UsbHostMgr.h" -#include "UsbEndpoint.h" -#include "UsbBaseClass.h" -#include "FATFileSystem.h" - -#define SCSI_CMD_REQUEST_SENSE 0x03 -#define SCSI_CMD_TEST_UNIT_READY 0x00 -#define SCSI_CMD_INQUIRY 0x12 -#define SCSI_CMD_READ_10 0x28 -#define SCSI_CMD_READ_CAPACITY 0x25 -#define SCSI_CMD_WRITE_10 0x2A - -#pragma pack(push,1) -typedef struct stcbw { - uint32_t dCBWSignature; - uint32_t dCBWTag; - uint32_t dCBWDataTraansferLength; - uint8_t bmCBWFlags; - uint8_t bCBWLUN; - uint8_t bCBWCBLength; - uint8_t CBWCB[16]; -} CBW; - -typedef struct stcsw { - uint32_t dCSWSignature; - uint32_t dCSWTag; - uint32_t dCSWDataResidue; - uint8_t bCSWStatus; -} CSW; -#pragma pack(pop) - -class msc : public FATFileSystem, public UsbBaseClass { -public: - msc(const char* name = NULL, int drive = 0); - virtual int disk_initialize(); - virtual int disk_write(const uint8_t *buffer, uint64_t block_number); - virtual int disk_read(uint8_t *buffer, uint64_t block_number); - virtual int disk_status(); - virtual int disk_sync(); - virtual uint64_t disk_sectors(); - - int setup(int timeout = 9000); - void _test(); -private: - int ParseConfiguration(); - int BulkOnlyMassStorageReset(); - int GetMaxLUN(); - int ReadCapacity(); - int GetSenseInfo(); - int TestUnitReady(); - int Inquire(); - int MS_BulkRecv(uint32_t block_number, int num_blocks, uint8_t* user_buffer); - int MS_BulkSend(uint32_t block_number, int num_blocks, uint8_t* user_buffer); - int CommandTransport(const uint8_t* cdb, int size); - int StatusTransport(); - int _bulkRecv(uint8_t* buf, int size); - int _bulkSend(uint8_t* buf, int size); - const char* m_name; - int m_drive; - uint32_t m_numBlocks; - int m_BlockSize; - int m_lun; - int m_MaxLUN; - int m_interface; - uint32_t m_tag; - CBW m_CBW; - CSW m_CSW; - UsbDevice* m_pDev; - UsbEndpoint* m_pEpBulkIn; - UsbEndpoint* m_pEpBulkOut; -}; - -#endif // MSC_H
--- a/uvchost.lib Wed Dec 05 12:41:25 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/va009039/code/uvchost/#3eb41d749f9a