Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FatFileSystem TB6612FNG2 mbed
Diff: uvc/uvc.cpp
- Revision:
- 0:de03cbbcd0ff
diff -r 000000000000 -r de03cbbcd0ff uvc/uvc.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uvc/uvc.cpp Mon Nov 30 09:32:15 2015 +0000
@@ -0,0 +1,264 @@
+#include "mbed.h"
+#include "uvc.h"
+
+//#define __DEBUG
+//#define __DEBUG3
+#include "mydbg.h"
+#include "usb_itd.h"
+
+uvc::uvc(int cam)
+{
+ DBG("cam=%d\n", cam);
+ DBG_ASSERT(cam >= 0);
+ m_cam = cam;
+ m_init = false;
+ m_connect = false;
+ m_int_seq = 0;
+ m_iso_seq = 0;
+ m_width = 0;
+ m_height = 0;
+ m_payload = PAYLOAD_MJPEG;
+ m_FormatIndex = 0;
+ m_FrameIndex = 0;
+ m_FrameInterval = 0;
+ m_PacketSize = 0;
+ m_stream = NULL;
+ for(int i = 0; i <= 15; i++) {
+ ReportConditionCode[i] = 0;
+ }
+ clearOnResult();
+}
+
+uvc::~uvc()
+{
+ clearOnResult();
+}
+
+int uvc::setup()
+{
+ if (!m_init) {
+ return _init();
+ }
+ return 0;
+}
+
+int uvc::get_jpeg(const char* path)
+{
+ const int size = 4800;
+ const int timeout = 5000;
+ uint8_t* buf = new uint8_t[size];
+ DBG_ASSERT(buf);
+ if (buf == NULL) {
+ return -1;
+ }
+ usb_mjpeg mjpeg(buf, size);
+ attach(&mjpeg);
+ Timer t;
+ t.reset();
+ t.start();
+ while(t.read_ms() < timeout) {
+ int stat = isochronous();
+ if (mjpeg.status() >= 0) {
+ break;
+ }
+ }
+ detach();
+ int len = mjpeg.status();
+ if (len >= 0) {
+ if (path != NULL) {
+ FILE *fp = fopen(path, "wb");
+ if (fp != NULL) {
+ for(int i = 0; i < len; i++) {
+ fputc(buf[i], fp);
+ }
+ fclose(fp);
+ }
+ }
+ }
+ delete[] buf;
+ return len;
+}
+
+int uvc::get_jpeg(uint8_t* buf, int size)
+{
+ //DBG("buf=%p size=%d\n", buf, size);
+ const int timeout = 5000;
+ usb_mjpeg mjpeg(buf, size);
+ attach(&mjpeg);
+ Timer t;
+ t.reset();
+ t.start();
+ while(t.read_ms() < timeout) {
+ int stat = isochronous();
+ if (mjpeg.status() >= 0) {
+ break;
+ }
+ }
+ detach();
+ int len = mjpeg.status();
+ return len;
+}
+
+bool uvc::interrupt()
+{
+ if (!m_init) {
+ _init();
+ }
+ if (m_int_seq == 0) {
+ int rc = m_pEpIntIn->transfer(m_int_buf, sizeof(m_int_buf));
+ if (rc != USBERR_PROCESSING) {
+ return false;
+ }
+ m_int_seq++;
+ }
+ int len = m_pEpIntIn->status();
+ if (len > 0) {
+ m_int_seq = 0;
+ DBG_BYTES("interrupt", m_int_buf, len);
+ return true;
+ }
+ return false;
+}
+
+#define CC_NOERROR 0x0
+#define CC_DATAOVERRUN 0x8
+#define CC_DATAUNDERRUN 0x9
+
+inline void DI()
+{
+ NVIC_DisableIRQ(USB_IRQn);
+}
+
+inline void EI()
+{
+ NVIC_EnableIRQ(USB_IRQn);
+}
+
+int uvc::isochronous()
+{
+ if (m_iso_seq == 0) {
+ uint16_t frame = LPC_USB->HcFmNumber;
+ m_iso_frame = frame + 10; // 10msec
+ DBG_ASSERT(m_pEpIsoIn->m_itdActive == 0);
+ m_iso_seq++;
+ }
+ if (m_iso_seq == 1) {
+ DBG_ASSERT(m_itdCount > 0 && m_itdCount <= 8);
+ while(m_pEpIsoIn->m_itdActive < m_itdCount) {
+ int len = m_PacketSize * m_FrameCount;
+ uint8_t* buf = (uint8_t*)usb_get_bp(len);
+ if (buf == NULL) {
+ DBG("len=%d\n", len);
+ DBG("m_itdCount=%d\n", m_itdCount);
+ }
+ DBG_ASSERT(buf);
+ int rc = m_pEpIsoIn->transfer(m_iso_frame, m_FrameCount, buf, len);
+ m_iso_frame += m_FrameCount;
+ DBG_ASSERT(rc == USBERR_PROCESSING);
+ }
+ m_iso_seq++;
+ }
+ if (m_iso_seq == 2) {
+ //DBG("frame:%04X\n", LPC_USB->HcFmNumber);
+ while(1) {
+ DI();
+ bool empty = m_pEpIsoIn->queue_done_itd.empty();
+ EI();
+
+ if (empty) {
+ break;
+ }
+
+ DI();
+ HCITD* itd = m_pEpIsoIn->queue_done_itd.front();
+ m_pEpIsoIn->queue_done_itd.pop();
+ EI();
+
+ m_pEpIsoIn->m_itdActive--;
+ usb_itd iso_td(itd);
+ //DBG("frame:%04X\n", LPC_USB->HcFmNumber);
+ //DBG("itd->Control=%08X\n", itd->Control);
+ int cc = iso_td.ConditionCode();
+ DBG_ASSERT(cc >= 0 && cc <= 15);
+ ReportConditionCode[cc]++;
+ if (cc != CC_NOERROR) {
+ DBG3("%04X ERR:%X\n", LPC_USB->HcFmNumber, cc);
+ iso_td.free();
+ m_iso_seq = 3;
+ return -1;
+ }
+ uint16_t frame = iso_td.StartingFrame();
+ int fc = iso_td.FrameCount();
+ for(int i = 0; i < fc; i++) {
+ int len = iso_td.Length(i);
+ if (len > 0) {
+ if (m_stream) {
+ m_stream->input(frame+i, iso_td.BufferPage(i, m_PacketSize), len);
+ }
+ onResult(frame+i, iso_td.BufferPage(i, m_PacketSize), len);
+ }
+ }
+ iso_td.free();
+ }
+ //DBG("frame:%04X\n", LPC_USB->HcFmNumber);
+ m_iso_seq = 1;
+ return m_pEpIsoIn->m_itdActive;
+ }
+ if (m_iso_seq == 3) { // cleanup
+ DBG("m_pEpIsoIn->queue_done_itd.size() :%d\n", m_pEpIsoIn->queue_done_itd.size());
+ while(1) {
+ DI();
+ bool empty = m_pEpIsoIn->queue_done_itd.empty();
+ EI();
+
+ if (empty) {
+ break;
+ }
+
+ DI();
+ HCITD* itd = m_pEpIsoIn->queue_done_itd.front();
+ m_pEpIsoIn->queue_done_itd.pop();
+ EI();
+
+ m_pEpIsoIn->m_itdActive--;
+ usb_itd iso_td(itd);
+ iso_td.free();
+ }
+ if (m_pEpIsoIn->m_itdActive == 0) {
+ m_iso_seq = 0;
+ }
+ }
+ return m_pEpIsoIn->m_itdActive;
+}
+
+void uvc::attach(usb_stream* stream)
+{
+ m_stream = stream;
+}
+
+void uvc::detach()
+{
+ m_stream = NULL;
+}
+
+void uvc::onResult(uint16_t frame, uint8_t* buf, int len)
+{
+ if(m_pCbItem && m_pCbMeth)
+ (m_pCbItem->*m_pCbMeth)(frame, buf, len);
+ else if(m_pCb)
+ m_pCb(frame, buf, len);
+}
+
+void uvc::setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) )
+{
+ m_pCb = pMethod;
+ m_pCbItem = NULL;
+ m_pCbMeth = NULL;
+}
+
+void uvc::clearOnResult()
+{
+ m_pCb = NULL;
+ m_pCbItem = NULL;
+ m_pCbMeth = NULL;
+}