Masato YAMANISHI / Mbed 2 deprecated USBHostC210_example

Dependencies:   TextLCD USBHost mbed

Fork of USBHostC270_example by Norimasa Okamoto

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BaseUvc.cpp Source File

BaseUvc.cpp

00001 // BaseUvc.cpp
00002 
00003 #include "USBHostConf.h"
00004 #include "USBHost.h"
00005 
00006 #include "BaseUvc.h"
00007 
00008 //#define ISO_DEBUG 1
00009 #ifdef ISO_DEBUG
00010 #define ISO_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
00011 #else
00012 #define ISO_DBG(...)  while(0);
00013 #endif
00014 
00015 #define TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
00016 
00017 void BaseUvc::poll(int millisec)
00018 {
00019     HCITD* itd = m_isoEp->isochronousReceive(millisec);
00020     if (itd) {
00021         uint8_t cc = itd->ConditionCode();
00022         report_cc_count[cc]++;
00023         if (cc == 0) {
00024             uint16_t frame = itd->StartingFrame();
00025             int fc = itd->FrameCount();
00026             uint8_t* buf = const_cast<uint8_t*>(itd->buf); 
00027             int mps = m_isoEp->m_PacketSize;
00028             for(int i = 0; i < fc; i++) {
00029                 uint16_t psw = itd->OffsetPSW[i];
00030                 cc = psw>>12;
00031                 if (cc == 0 || cc == 9) {
00032                     int len = psw & 0x7ff;
00033                     onResult(frame, buf, len);
00034                }
00035                report_ps_cc_count[cc]++;
00036                buf += mps;
00037                frame++;
00038             }
00039         }
00040         delete itd;
00041     }
00042 }
00043 
00044 USB_TYPE BaseUvc::Control(int req, int cs, int index, uint8_t* buf, int size)
00045 {
00046     if (req == SET_CUR) {    
00047         return host->controlWrite(dev,
00048                     USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, 
00049                     req, cs<<8, index, buf, size);
00050     }
00051     return host->controlRead(dev,
00052                 USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, 
00053                 req, cs<<8, index, buf, size);
00054 }
00055 
00056 USB_TYPE BaseUvc::setInterfaceAlternate(uint8_t intf, uint8_t alt)
00057 {
00058     return host->controlWrite(dev, USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE,
00059                                    SET_INTERFACE, alt, intf, NULL, 0);
00060 }
00061 
00062 void BaseUvc::onResult(uint16_t frame, uint8_t* buf, int len)
00063 {
00064   if(m_pCbItem && m_pCbMeth)
00065     (m_pCbItem->*m_pCbMeth)(frame, buf, len);
00066   else if(m_pCb)
00067     m_pCb(frame, buf, len);
00068 }
00069 
00070 void BaseUvc::setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) )
00071 {
00072     m_pCb = pMethod;
00073     m_pCbItem = NULL;
00074     m_pCbMeth = NULL;
00075 }
00076     
00077 void BaseUvc::clearOnResult()
00078 {
00079     m_pCb = NULL;
00080     m_pCbItem = NULL;
00081     m_pCbMeth = NULL;
00082 }
00083 
00084 
00085 HCITD::HCITD(BaseEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) {
00086     Control = 0xe0000000           | // CC ConditionCode NOT ACCESSED
00087              ((FrameCount-1) << 24)| // FC FrameCount
00088                   TD_DELAY_INT(0)  | // DI DelayInterrupt
00089                  FrameNumber;        // SF StartingFrame
00090     BufferPage0 = const_cast<uint8_t*>(buf);
00091     BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1;
00092     Next = NULL; 
00093     ep = obj;
00094     uint32_t addr = reinterpret_cast<uint32_t>(buf);
00095     for(int i = 0; i < FrameCount; i++) {
00096         uint16_t offset = addr & 0x0fff;
00097         if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) {
00098             offset |= 0x1000;
00099         }
00100         OffsetPSW[i] = 0xe000|offset;
00101         addr += PacketSize;
00102     }
00103 }
00104 
00105 IsochronousEp::IsochronousEp(int addr, uint8_t ep, uint16_t size):BaseEp(addr, ep, size)
00106 {
00107     ISO_DBG("%p FA:%d EP:%02X MPS:%d\n", this, addr, ep, size);
00108     TEST_ASSERT(m_pED);
00109     
00110     m_pED->Control |= (1 << 15); // F Format ITD
00111 
00112     TEST_ASSERT(size >= 128 && size <= 1023);
00113     m_PacketSize = size;
00114     m_FrameCount = 4; // 1-8
00115     TEST_ASSERT(m_FrameCount >= 1 && m_FrameCount <= 8);
00116     m_itd_queue_count = 0;
00117     reset();
00118     HCITD* itd = new_HCITD(this);
00119     m_pED->TailTd = reinterpret_cast<HCTD*>(itd);
00120     m_pED->HeadTd = reinterpret_cast<HCTD*>(itd); 
00121     TEST_ASSERT(itd);
00122     if (itd == NULL) {
00123         return;
00124     }
00125     _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA);
00126     TEST_ASSERT(hcca);
00127     if (hcca == NULL) {
00128         return;
00129     }
00130     hcca->enqueue(m_pED);
00131 }
00132 
00133 void IsochronousEp::reset(int delay_ms)
00134 {
00135     m_FrameNumber = LPC_USB->HcFmNumber + delay_ms;
00136 }
00137 
00138 HCITD* IsochronousEp::new_HCITD(BaseEp* obj)
00139 {
00140     HCITD* itd = new(m_PacketSize*m_FrameCount)HCITD(obj, m_FrameNumber, m_FrameCount, m_PacketSize);
00141     if (itd == NULL) {
00142         return NULL;
00143     } 
00144     m_FrameNumber += m_FrameCount;
00145     return itd;
00146 }
00147 
00148 HCITD* IsochronousEp::isochronousReceive(int millisec)
00149 {
00150     TEST_ASSERT(m_itd_queue_count >= 0);
00151     while(m_itd_queue_count < 3 && m_itd_queue_count < HCTD_QUEUE_SIZE) {
00152         HCITD* itd = reinterpret_cast<HCITD*>(m_pED->TailTd);
00153         TEST_ASSERT(itd);
00154         if (itd == NULL) {
00155             return NULL;
00156         }
00157         HCITD* blank_itd = new_HCITD(this);
00158         TEST_ASSERT(blank_itd);
00159         if (blank_itd == NULL) {
00160             return NULL;
00161         }
00162         itd->Next = blank_itd;
00163         m_pED->TailTd = reinterpret_cast<HCTD*>(blank_itd);
00164         m_itd_queue_count++;
00165         //DBG_IED(m_pED);
00166         enable(); // Enable Periodic
00167     }
00168     
00169     HCITD* itd = get_queue_HCITD(millisec);
00170     if (itd) {
00171         m_itd_queue_count--;
00172     }
00173     return itd;
00174 }
00175 
00176 HCITD* IsochronousEp::get_queue_HCITD(int millisec)
00177 {
00178     for(int i = 0; i < 16; i++) {
00179         osEvent evt = m_queue.get(millisec);
00180         if (evt.status == osEventMessage) {
00181             HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p);
00182             TEST_ASSERT(itd);
00183             return itd;
00184         } else if (evt.status == osOK) {
00185             continue;
00186         } else if (evt.status == osEventTimeout) {
00187             return NULL;
00188         } else {
00189             ISO_DBG("evt.status: %02x\n", evt.status);
00190             TEST_ASSERT(evt.status == osEventMessage);
00191             return NULL;
00192         }
00193     }
00194     return NULL;
00195 }
00196 
00197 void IsochronousEp::enable()
00198 {
00199     LPC_USB->HcControl |= OR_CONTROL_PLE;
00200 }
00201 
00202 void IsochronousEp::disconnect()
00203 {
00204     m_pED->setSkip();
00205     ISO_DBG("m_itd_queue_count: %d", m_itd_queue_count);
00206     Timer t;
00207     t.reset();
00208     t.start();
00209     while(m_itd_queue_count > 0 && t.read_ms() <= (8*3)) {
00210         HCITD* itd = get_queue_HCITD(0);
00211         if (itd) {
00212             ISO_DBG("ITD: %p", itd);
00213             delete itd;
00214             m_itd_queue_count--;
00215             t.reset();
00216         }
00217     }
00218     ISO_DBG("m_itd_queue_count: %d, t_ms: %d", m_itd_queue_count, t.read_ms());
00219     HCITD* head = reinterpret_cast<HCITD*>(reinterpret_cast<uint32_t>(m_pED->HeadTd)&~3); // delete Halted and Toggle Carry bit
00220     TEST_ASSERT(head);
00221     HCITD* tail = reinterpret_cast<HCITD*>(m_pED->TailTd);
00222     TEST_ASSERT(tail);
00223     while(head != tail) {
00224         HCITD* next = head->Next;
00225         TEST_ASSERT(next);
00226         ISO_DBG("ED ITD:%p next:%p", head, next);        
00227         delete head;
00228         TEST_ASSERT(m_itd_queue_count > 0);
00229         m_itd_queue_count--;
00230         head = next;
00231     }
00232     TEST_ASSERT(m_itd_queue_count == 0);
00233     delete head;
00234     
00235     _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA);
00236     TEST_ASSERT(hcca);
00237     hcca->dequeue(m_pED);
00238     delete m_pED;
00239 }
00240 
00241 BaseEp::BaseEp(int addr, uint8_t ep, uint16_t size, int lowSpeed):m_td_queue_count(0)
00242 {
00243     ISO_DBG("%p FA=%d EN=%02x MPS=%d S=%d\n", this, addr, ep, size, lowSpeed);
00244     TEST_ASSERT(size >= 8 && size <= 1023);    
00245     TEST_ASSERT(lowSpeed == 0 || lowSpeed == 1);
00246     m_pED  = new _HCED(addr, ep, size, lowSpeed);
00247     TEST_ASSERT(m_pED);
00248 }