Takao Aratani / uvchost

Dependents:   WebCamera_SD

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