convert JPEG stream data to bitmap, BaseJpegDecode example program
Dependencies: BaseJpegDecode BaseUsbHost FATFileSystem mbed-rtos mbed
JPEGデコードのサンプルプログラムです。
JPEGのMCU単位で逐次デコード出力していますので少ないRAMメモリで動かすことが出来ます。
#include "USBHostMSD.h" #include "SimpleJpegDecode.h" #include "bmp24.h" const char* INPUT_FILE = "/usb/input.jpg"; const char* OUTPUT_FILE = "/usb/output.bmp"; bmp24 bmp; RawSerial pc(USBTX, USBRX); void callbackRGB(int x, int y, uint8_t* rgb) { bmp.point(x, y, rgb); pc.printf("x=%d, y=%d, RGB=(0x%02x,0x%02x,0x%02x)\n", x, y, rgb[0], rgb[1], rgb[2]); } int main() { pc.baud(115200); USBHostMSD* msd = new USBHostMSD("usb"); if (!msd->connect()) { error("USB Flash drive not found.\n"); } SimpleJpegDecode* decode = new SimpleJpegDecode(RGB24); decode->setOnResult(callbackRGB); decode->clear(); pc.printf("input: %s\n", INPUT_FILE); FILE* fp = fopen(INPUT_FILE, "rb"); if (fp == NULL) { error("open error\n"); } while(1) { int c = fgetc(fp); if (c == EOF) { break; } decode->input(c); } fclose(fp); pc.printf("output: %s\n", OUTPUT_FILE); if (!bmp.writeFile(OUTPUT_FILE)) { error("write error\n"); } exit(1); }
Revision 0:98f918e1d528, committed 2013-02-02
- Comitter:
- va009039
- Date:
- Sat Feb 02 01:25:25 2013 +0000
- Commit message:
- first commit
Changed in this revision
diff -r 000000000000 -r 98f918e1d528 BaseJpegDecode.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BaseJpegDecode.lib Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/va009039/code/BaseJpegDecode/#d7ee458cacd1
diff -r 000000000000 -r 98f918e1d528 BaseUsbHost.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BaseUsbHost.lib Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/va009039/code/BaseUsbHost/#d931d24c2f81
diff -r 000000000000 -r 98f918e1d528 FATFileSystem.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FATFileSystem.lib Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/va009039/code/FATFileSystem/#86638c0f65b0
diff -r 000000000000 -r 98f918e1d528 SimpleJpegDecode/SimpleJpegDecode.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SimpleJpegDecode/SimpleJpegDecode.cpp Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,161 @@ +#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; +}
diff -r 000000000000 -r 98f918e1d528 SimpleJpegDecode/SimpleJpegDecode.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SimpleJpegDecode/SimpleJpegDecode.h Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,56 @@ +#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
diff -r 000000000000 -r 98f918e1d528 UsbFlashDrive/UsbFlashDrive.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UsbFlashDrive/UsbFlashDrive.cpp Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,406 @@ +// UsbFlashDrive.cpp 2013/1/25 +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +//#define DEBUG +#include "BaseUsbHostDebug.h" +#define TEST +#include "BaseUsbHostTest.h" +#include "UsbFlashDrive.h" + +//#define WRITE_PROTECT + + +uint32_t BE32(uint8_t* d) +{ + return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3]; +} + +void BE16(uint32_t n, uint8_t* d) +{ + d[0] = (uint8_t)(n >> 8); + d[1] = (uint8_t)n; +} + +void BE32(uint32_t n, uint8_t* d) +{ + d[0] = (uint8_t)(n >> 24); + d[1] = (uint8_t)(n >> 16); + d[2] = (uint8_t)(n >> 8); + d[3] = (uint8_t)n; +} + +UsbFlashDrive::UsbFlashDrive(const char* name, ControlEp* ctlEp): FATFileSystem(name) +{ + m_name = name; + + if (ctlEp == NULL) { // root hub + DBG_OHCI(LPC_USB->HcRhPortStatus1); + TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200); + ctlEp = new ControlEp(); + TEST_ASSERT_TRUE(ctlEp); + } + + CTASSERT(sizeof(CBW) == 31); + CTASSERT(sizeof(CSW) == 13); + TEST_ASSERT(sizeof(CBW) == 31); + TEST_ASSERT(sizeof(CSW) == 13); + + m_numBlocks = 0; + m_BlockSize = 0; + m_lun = 0; + m_interface = 0; + m_pEpBulkIn = NULL; + m_pEpBulkOut = NULL; + + ParseConfiguration(ctlEp); + int rc = ctlEp->SetConfiguration(1); + TEST_ASSERT_EQUAL(rc, USB_OK); + GetMaxLUN(ctlEp); + setup(ctlEp); +} + +bool UsbFlashDrive::check(ControlEp* ctlEp) +{ + if (ctlEp == NULL) { + return false; + } + CTASSERT(sizeof(StandardDeviceDescriptor) == 18); + CTASSERT(sizeof(StandardConfigurationDescriptor) == 9); + CTASSERT(sizeof(StandardInterfaceDescriptor) == 9); + TEST_ASSERT(sizeof(StandardDeviceDescriptor) == 18); + TEST_ASSERT(sizeof(StandardConfigurationDescriptor) == 9); + TEST_ASSERT(sizeof(StandardInterfaceDescriptor) == 9); + + StandardDeviceDescriptor desc; + int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_DEVICE, 0, reinterpret_cast<uint8_t*>(&desc), sizeof(StandardDeviceDescriptor)); + if (rc != USB_OK) { + return false; + } + if (desc.bDeviceClass == 8) { + return true; + } else if (desc.bDeviceClass != 0x00) { + return false; + } + uint8_t temp[4]; + rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, temp, sizeof(temp)); + if (rc != USB_OK) { + return false; + } + StandardConfigurationDescriptor* cfg = reinterpret_cast<StandardConfigurationDescriptor*>(temp); + uint8_t* buf = new uint8_t[cfg->wTotalLength]; + + rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, cfg->wTotalLength); + if (rc != USB_OK) { + return false; + } + DBG_HEX(buf, cfg->wTotalLength); + bool ret = false; + for(int pos = 0; pos < cfg->wTotalLength; pos += buf[pos]) { + StandardInterfaceDescriptor* desc = reinterpret_cast<StandardInterfaceDescriptor*>(buf+pos); + if (desc->bDescriptorType == 4) { // interface ? + if (desc->bInterfaceClass == 8 && desc->bInterfaceSubClass == 6 && desc->bInterfaceProtocol == 0x50) { + ret = true; + } + break; + } + } + delete[] buf; + return ret; +} + +int UsbFlashDrive::disk_initialize() +{ + //DBG("m_BlockSize=%d\n", m_BlockSize); + if (m_BlockSize != 512) { + return 1; + } + return 0; +} + +int UsbFlashDrive::disk_write(const uint8_t* buffer, uint64_t sector) +{ + m_report_disk_write++; + //DBG("buffer=%p block_number=%d\n", buffer, sector); + int ret = MS_BulkSend(sector, 1, buffer); + if (ret >= 0) { + return 0; + } + return 1; +} + +int UsbFlashDrive::disk_read(uint8_t* buffer, uint64_t sector) +{ + m_report_disk_read++; + //DBG("buffer=%p block_number=%d\n", buffer, sector); + int ret = MS_BulkRecv(sector, 1, buffer); + if (ret >= 0) { + return 0; + } + return 1; +} + +int UsbFlashDrive::disk_status() +{ + m_report_disk_status++; + return 0; +} + +int UsbFlashDrive::disk_sync() +{ + m_report_disk_sync++; + return 0; +} + +uint64_t UsbFlashDrive::disk_sectors() +{ + DBG("m_numBlocks=%d\n", m_numBlocks); + return m_numBlocks; +} + +int UsbFlashDrive::setup(ControlEp* ctlEp, int timeout) +{ + + 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 == USB_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; +} + +int UsbFlashDrive::ParseConfiguration(ControlEp* ctlEp) +{ + TEST_ASSERT(ctlEp); + TEST_ASSERT(sizeof(StandardEndpointDescriptor) == 7); + uint8_t temp[4]; + int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, temp, sizeof(temp)); + if (rc != USB_OK) { + return rc; + } + StandardConfigurationDescriptor* cfg = reinterpret_cast<StandardConfigurationDescriptor*>(temp); + uint8_t* buf = new uint8_t[cfg->wTotalLength]; + rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, cfg->wTotalLength); + if (rc != USB_OK) { + return rc; + } + DBG_HEX(buf, cfg->wTotalLength); + for(int pos = 0; pos < cfg->wTotalLength; pos += buf[pos]) { + StandardEndpointDescriptor* desc = reinterpret_cast<StandardEndpointDescriptor*>(buf+pos); + if (desc->bDescriptorType == USB_DESCRIPTOR_TYPE_ENDPOINT) { + if (desc->bmAttributes == 2) { // bulk + BulkEp* pEp = new BulkEp(ctlEp->GetAddr(), desc->bEndpointAddress, desc->wMaxPacketSize); + if (desc->bEndpointAddress & 0x80) { + m_pEpBulkIn = pEp; + } else { + m_pEpBulkOut = pEp; + } + } + } + } + delete[] buf; + if (m_pEpBulkIn && m_pEpBulkOut) { + return USB_OK; + } + return USB_ERROR; +} + +int UsbFlashDrive::BulkOnlyMassStorageReset(ControlEp* ctlEp) +{ + TEST_ASSERT(ctlEp); + int rc = ctlEp->controlReceive(0x21, 0xff, 0x0000, m_interface, NULL, 0); + TEST_ASSERT(rc == USB_OK); + return rc; +} + +int UsbFlashDrive::GetMaxLUN(ControlEp* ctlEp) +{ + TEST_ASSERT(ctlEp); + TEST_ASSERT(m_interface == 0); + uint8_t temp[1]; + int rc = ctlEp->controlReceive(0xa1, 0xfe, 0x0000, m_interface, temp, sizeof(temp)); + TEST_ASSERT(rc == USB_OK); + DBG_BYTES("GetMaxLUN", temp, sizeof(temp)); + m_MaxLUN = temp[0]; + TEST_ASSERT(m_MaxLUN <= 15); + return rc; +} + + +int UsbFlashDrive::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 UsbFlashDrive::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(); + TEST_ASSERT(m_CSW.bCSWStatus == 0x00); + return 0; +} + +int UsbFlashDrive::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)); + TEST_ASSERT(rc >= 0); + DBG_HEX(buf, sizeof(buf)); + + StatusTransport(); + TEST_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); + TEST_ASSERT(m_BlockSize == 512); + TEST_ASSERT(m_numBlocks > 0); + return 0; +} + +int UsbFlashDrive::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]; + int rc = _bulkRecv(buf, sizeof(buf)); + TEST_ASSERT(rc >= 0); + DBG_HEX(buf, sizeof(buf)); + + StatusTransport(); + return 0; +} + +int UsbFlashDrive::MS_BulkRecv(uint32_t block_number, int num_blocks, uint8_t* user_buffer) +{ + TEST_ASSERT(m_BlockSize == 512); + TEST_ASSERT(num_blocks == 1); + TEST_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; + TEST_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(); + TEST_ASSERT(m_CSW.bCSWStatus == 0x00); + return ret; +} + +int UsbFlashDrive::MS_BulkSend(uint32_t block_number, int num_blocks, const uint8_t* user_buffer) +{ +#ifdef WRITE_PROTECT + return 0; +#else + TEST_ASSERT(num_blocks == 1); + TEST_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; + TEST_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(); + TEST_ASSERT(m_CSW.bCSWStatus == 0x00); + return ret; +#endif //WRITE_PROTECT +} + +int UsbFlashDrive::CommandTransport(const uint8_t* cdb, int size) +{ + TEST_ASSERT(cdb); + TEST_ASSERT(size >= 6); + TEST_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 UsbFlashDrive::StatusTransport() +{ + TEST_ASSERT(sizeof(CSW) == 13); + int rc = _bulkRecv((uint8_t*)&m_CSW, sizeof(CSW)); + //DBG_HEX((uint8_t*)&m_CSW, sizeof(CSW)); + TEST_ASSERT(m_CSW.dCSWSignature == 0x53425355); + TEST_ASSERT(m_CSW.dCSWTag == m_CBW.dCBWTag); + TEST_ASSERT(m_CSW.dCSWDataResidue == 0); + return rc; +} + +int UsbFlashDrive::_bulkRecv(uint8_t* buf, int size) +{ + TEST_ASSERT(m_pEpBulkIn); + int ret = m_pEpBulkIn->bulkReceive(buf, size); + return ret; +} + +int UsbFlashDrive::_bulkSend(const uint8_t* buf, int size) +{ + TEST_ASSERT(m_pEpBulkOut); + int ret = m_pEpBulkOut->bulkSend(buf, size); + return ret; +}
diff -r 000000000000 -r 98f918e1d528 UsbFlashDrive/UsbFlashDrive.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UsbFlashDrive/UsbFlashDrive.h Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,75 @@ +// usbFlashDrive.h 2013/1/8 +#pragma once + +#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) +struct CBW { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTraansferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}; + +struct CSW { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}; +#pragma pack(pop) + +class UsbFlashDrive : public FATFileSystem { +public: + UsbFlashDrive(const char* name, ControlEp* ctlEp = NULL); + static bool check(ControlEp* ctlEp); + virtual int disk_initialize(); + virtual int disk_write(const uint8_t* buffer, uint64_t sector); + virtual int disk_read(uint8_t* buffer, uint64_t sector); + virtual int disk_status(); + virtual int disk_sync(); + virtual uint64_t disk_sectors(); +private: + int setup(ControlEp* ctlEp, int timeout = 9000); + int ParseConfiguration(ControlEp* ctlEp); + int BulkOnlyMassStorageReset(ControlEp* ctlEp); + int GetMaxLUN(ControlEp* ctlEp); + 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, const uint8_t* user_buffer); + int CommandTransport(const uint8_t* cdb, int size); + int StatusTransport(); + int _bulkRecv(uint8_t* buf, int size); + int _bulkSend(const 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; + // endpoint + BulkEp* m_pEpBulkIn; + BulkEp* m_pEpBulkOut; + // report + uint32_t m_report_disk_write; + uint32_t m_report_disk_read; + uint32_t m_report_disk_status; + uint32_t m_report_disk_sync; +};
diff -r 000000000000 -r 98f918e1d528 bmp24.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bmp24.h Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,66 @@ +#ifndef BMP24_H +#define BMP24_H + +#define BMP24_WIDTH (16*4) +#define BMP24_HEIGHT (16*3) + +class bmp24 { + uint8_t m_bitmap[BMP24_WIDTH*BMP24_HEIGHT*3]; +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; + } + + bool writeFile(const char *path) { + FILE *fp = fopen(path, "wb"); + if (fp == NULL) { + return false; + } + 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); + return true; + } +}; + +#endif // BMP24_H
diff -r 000000000000 -r 98f918e1d528 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,57 @@ +// SimpleJpegDecode_example/main.cpp 2013/2/2 +// convert jpeg to bmp +// +#include "mbed.h" +#include "rtos.h" +#include "BaseUsbHost.h" +#include "SimpleJpegDecode.h" +#include "UsbFlashDrive.h" +#include "bmp24.h" + +#define INPUT_FILE "/usb/input.jpg" +#define OUTPUT_FILE "/usb/output.bmp" + +Serial pc(USBTX, USBRX); + +SimpleJpegDecode decode; +bmp24 bmp; + +void callbackRGB(int x, int y, uint8_t* rgb) +{ + bmp.point(x, y, rgb); +} + +int main() { + pc.baud(921600); + printf("%s\n", __FILE__); + + BaseUsbHost* usbHost = new BaseUsbHost(); + ControlEp* ctlEp = new ControlEp; // root hub + if (UsbHub::check(ctlEp)) { + UsbHub* hub = new UsbHub(ctlEp); + ctlEp = hub->search<UsbFlashDrive>(); + } + if (!UsbFlashDrive::check(ctlEp)) { + error("USB flash drive is not connected.\n"); + } + UsbFlashDrive* drive = new UsbFlashDrive("usb", ctlEp); + + bmp.clear(); + decode.setOnResult(callbackRGB); + decode.clear(); + printf("input: %s\n", INPUT_FILE); + FILE* fp = fopen(INPUT_FILE, "rb"); + if (fp == NULL) { + error("open error\n"); + } + while(!feof(fp)) { + int c = fgetc(fp); + decode.input(c); + } + fclose(fp); + printf("output: %s\n", OUTPUT_FILE); + if (!bmp.writeFile(OUTPUT_FILE)) { + error("write error\n"); + } + exit(1); +}
diff -r 000000000000 -r 98f918e1d528 mbed-rtos.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed-rtos/#53e6cccd8782
diff -r 000000000000 -r 98f918e1d528 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sat Feb 02 01:25:25 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/0954ebd79f59 \ No newline at end of file