BLE demo for mbed Ported RunningElectronics's SBDBT firmware for BLE. It can communicate with iOS

Dependencies:   FatFileSystem mbed

Fork of BTstack by Norimasa Okamoto

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers uvc.cpp Source File

uvc.cpp

00001 #include "mbed.h"
00002 #include "uvc.h"
00003 
00004 //#define __DEBUG
00005 //#define __DEBUG3
00006 #include "mydbg.h"
00007 #include "usb_itd.h"
00008 
00009 uvc::uvc(int cam)
00010 {
00011     DBG("cam=%d\n", cam);
00012     DBG_ASSERT(cam >= 0);
00013     m_cam = cam;
00014     m_init = false;
00015     m_connect = false;
00016     m_int_seq = 0;
00017     m_iso_seq = 0;
00018     m_width = 0;
00019     m_height = 0;
00020     m_payload = PAYLOAD_MJPEG;
00021     m_FormatIndex = 0;
00022     m_FrameIndex = 0;
00023     m_FrameInterval = 0;
00024     m_PacketSize = 0;
00025     m_stream = NULL;
00026     for(int i = 0; i <= 15; i++) {
00027         ReportConditionCode[i] = 0;
00028     }
00029     clearOnResult();
00030 }
00031 
00032 uvc::~uvc()
00033 {
00034     clearOnResult();
00035 }
00036 
00037 int uvc::setup()
00038 {
00039     if (!m_init) {
00040         return _init();
00041     }
00042     return 0;
00043 }
00044 
00045 int uvc::get_jpeg(const char* path)
00046 {
00047     const int size = 4800;
00048     const int timeout = 5000;
00049     uint8_t* buf = new uint8_t[size];
00050     DBG_ASSERT(buf);
00051     if (buf == NULL) {
00052         return -1;
00053     }
00054     usb_mjpeg mjpeg(buf, size);
00055     attach(&mjpeg);
00056     Timer t;
00057     t.reset();
00058     t.start();
00059     while(t.read_ms() < timeout) {
00060         int stat = isochronous();
00061         if (mjpeg.status() >= 0) {
00062             break;
00063         }
00064     }
00065     detach();
00066     int len = mjpeg.status();
00067     if (len >= 0) {
00068         if (path != NULL) {
00069             FILE *fp = fopen(path, "wb");
00070             if (fp != NULL) {
00071                 for(int i = 0; i < len; i++) {
00072                     fputc(buf[i], fp);
00073                 }
00074                 fclose(fp);
00075             }
00076         }    
00077     }
00078     delete[] buf;
00079     return len;
00080 }
00081 
00082 int uvc::get_jpeg(uint8_t* buf, int size)
00083 {
00084     //DBG("buf=%p size=%d\n", buf, size);
00085     const int timeout = 5000;
00086     usb_mjpeg mjpeg(buf, size);
00087     attach(&mjpeg);
00088     Timer t;
00089     t.reset();
00090     t.start();
00091     while(t.read_ms() < timeout) {
00092         int stat = isochronous();
00093         if (mjpeg.status() >= 0) {
00094             break;
00095         }
00096     }
00097     detach();
00098     int len = mjpeg.status();
00099     return len;
00100 }
00101 
00102 bool uvc::interrupt()
00103 {
00104     if (!m_init) {
00105         _init();
00106     }
00107     if (m_int_seq == 0) {
00108         int rc = m_pEpIntIn->transfer(m_int_buf, sizeof(m_int_buf));
00109         if (rc != USBERR_PROCESSING) {
00110             return false;
00111         }
00112         m_int_seq++;
00113     }
00114     int len = m_pEpIntIn->status();
00115     if (len > 0) {
00116         m_int_seq = 0;
00117         DBG_BYTES("interrupt", m_int_buf, len);
00118         return true;
00119     }
00120     return false;
00121 }
00122 
00123 #define CC_NOERROR      0x0
00124 #define CC_DATAOVERRUN  0x8
00125 #define CC_DATAUNDERRUN 0x9
00126 
00127 inline void DI()
00128 {
00129     NVIC_DisableIRQ(USB_IRQn);
00130 }
00131 
00132 inline void EI()
00133 {
00134     NVIC_EnableIRQ(USB_IRQn);
00135 } 
00136 
00137 int uvc::isochronous()
00138 {
00139     if (m_iso_seq == 0) {
00140         uint16_t frame = LPC_USB->HcFmNumber;
00141         m_iso_frame = frame + 10; // 10msec
00142         DBG_ASSERT(m_pEpIsoIn->m_itdActive == 0);
00143         m_iso_seq++;
00144     }
00145     if (m_iso_seq == 1) {
00146         DBG_ASSERT(m_itdCount > 0 && m_itdCount <= 8);
00147         while(m_pEpIsoIn->m_itdActive < m_itdCount) {
00148             int len = m_PacketSize * m_FrameCount;
00149             uint8_t* buf = (uint8_t*)usb_get_bp(len);
00150             if (buf == NULL) {
00151                 DBG("len=%d\n", len);
00152                 DBG("m_itdCount=%d\n", m_itdCount);
00153             }
00154             DBG_ASSERT(buf);
00155             int rc = m_pEpIsoIn->transfer(m_iso_frame, m_FrameCount, buf, len);
00156             m_iso_frame += m_FrameCount;
00157             DBG_ASSERT(rc == USBERR_PROCESSING);
00158         }
00159         m_iso_seq++;
00160     }
00161     if (m_iso_seq == 2) {
00162         //DBG("frame:%04X\n", LPC_USB->HcFmNumber);
00163         while(1) {
00164             DI();
00165             bool empty = m_pEpIsoIn->queue_done_itd.empty();
00166             EI();
00167             
00168             if (empty) {
00169                 break;
00170             }
00171             
00172             DI();
00173             HCITD* itd = m_pEpIsoIn->queue_done_itd.front();
00174             m_pEpIsoIn->queue_done_itd.pop();
00175             EI();
00176             
00177             m_pEpIsoIn->m_itdActive--;
00178             usb_itd iso_td(itd);
00179             //DBG("frame:%04X\n", LPC_USB->HcFmNumber);
00180             //DBG("itd->Control=%08X\n", itd->Control); 
00181             int cc = iso_td.ConditionCode();
00182             DBG_ASSERT(cc >= 0 && cc <= 15);
00183             ReportConditionCode[cc]++;
00184             if (cc != CC_NOERROR) {
00185                 DBG3("%04X ERR:%X\n", LPC_USB->HcFmNumber, cc);
00186                 iso_td.free();
00187                 m_iso_seq = 3;
00188                 return -1;
00189             }
00190             uint16_t frame = iso_td.StartingFrame();
00191             int fc = iso_td.FrameCount();
00192             for(int i = 0; i < fc; i++) {
00193                 int len = iso_td.Length(i);
00194                 if (len > 0) {
00195                     if (m_stream) {
00196                         m_stream->input(frame+i, iso_td.BufferPage(i, m_PacketSize), len);
00197                     }
00198                     onResult(frame+i, iso_td.BufferPage(i, m_PacketSize), len);
00199                 }
00200             }
00201             iso_td.free();
00202         }
00203         //DBG("frame:%04X\n", LPC_USB->HcFmNumber);
00204         m_iso_seq = 1;
00205         return m_pEpIsoIn->m_itdActive;
00206     }
00207     if (m_iso_seq == 3) { // cleanup
00208         DBG("m_pEpIsoIn->queue_done_itd.size()  :%d\n", m_pEpIsoIn->queue_done_itd.size());
00209         while(1) {
00210             DI();
00211             bool empty = m_pEpIsoIn->queue_done_itd.empty();
00212             EI();
00213             
00214             if (empty) {
00215                 break;
00216             }
00217                        
00218             DI();
00219             HCITD* itd = m_pEpIsoIn->queue_done_itd.front();
00220             m_pEpIsoIn->queue_done_itd.pop();
00221             EI();
00222             
00223             m_pEpIsoIn->m_itdActive--;
00224             usb_itd iso_td(itd);
00225             iso_td.free();
00226         }
00227         if (m_pEpIsoIn->m_itdActive == 0) {
00228             m_iso_seq = 0;
00229         }
00230     }
00231     return m_pEpIsoIn->m_itdActive;
00232 }
00233 
00234 void uvc::attach(usb_stream* stream)
00235 {
00236     m_stream = stream;
00237 }
00238 
00239 void uvc::detach()
00240 {
00241     m_stream = NULL;
00242 }
00243 
00244 void uvc::onResult(uint16_t frame, uint8_t* buf, int len)
00245 {
00246   if(m_pCbItem && m_pCbMeth)
00247     (m_pCbItem->*m_pCbMeth)(frame, buf, len);
00248   else if(m_pCb)
00249     m_pCb(frame, buf, len);
00250 }
00251 
00252 void uvc::setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) )
00253 {
00254   m_pCb = pMethod;
00255   m_pCbItem = NULL;
00256   m_pCbMeth = NULL;
00257 }
00258 
00259 void uvc::clearOnResult()
00260 {
00261   m_pCb = NULL;
00262   m_pCbItem = NULL;
00263   m_pCbMeth = NULL;
00264 }