modify for C210 webcam and Startboard Orange.
Dependencies: TextLCD USBHost mbed
Fork of USBHostC270_example by
Norimasa Okamoto さんの http://mbed.org/users/va009039/code/USBHostC270_example/ を C210 webcam と StarBoard Orange での SD カード保存用に変更。
USBHostC270/BaseUvc.cpp@12:c827ed52021d, 2013-03-19 (annotated)
- Committer:
- masato
- Date:
- Tue Mar 19 14:16:25 2013 +0000
- Revision:
- 12:c827ed52021d
- Parent:
- 10:387c49b2fc7e
for C210 and StartBoard Orange
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 10:387c49b2fc7e | 1 | // BaseUvc.cpp |
va009039 | 10:387c49b2fc7e | 2 | |
va009039 | 9:fecabade834a | 3 | #include "USBHostConf.h" |
va009039 | 9:fecabade834a | 4 | #include "USBHost.h" |
va009039 | 9:fecabade834a | 5 | |
va009039 | 9:fecabade834a | 6 | #include "BaseUvc.h" |
va009039 | 9:fecabade834a | 7 | |
va009039 | 10:387c49b2fc7e | 8 | //#define ISO_DEBUG 1 |
va009039 | 10:387c49b2fc7e | 9 | #ifdef ISO_DEBUG |
va009039 | 10:387c49b2fc7e | 10 | #define ISO_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); |
va009039 | 10:387c49b2fc7e | 11 | #else |
va009039 | 10:387c49b2fc7e | 12 | #define ISO_DBG(...) while(0); |
va009039 | 10:387c49b2fc7e | 13 | #endif |
va009039 | 10:387c49b2fc7e | 14 | |
va009039 | 9:fecabade834a | 15 | #define TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; |
va009039 | 9:fecabade834a | 16 | |
va009039 | 9:fecabade834a | 17 | void BaseUvc::poll(int millisec) |
va009039 | 9:fecabade834a | 18 | { |
va009039 | 10:387c49b2fc7e | 19 | HCITD* itd = m_isoEp->isochronousReceive(millisec); |
va009039 | 9:fecabade834a | 20 | if (itd) { |
va009039 | 9:fecabade834a | 21 | uint8_t cc = itd->ConditionCode(); |
va009039 | 9:fecabade834a | 22 | report_cc_count[cc]++; |
va009039 | 9:fecabade834a | 23 | if (cc == 0) { |
va009039 | 9:fecabade834a | 24 | uint16_t frame = itd->StartingFrame(); |
va009039 | 9:fecabade834a | 25 | int fc = itd->FrameCount(); |
va009039 | 9:fecabade834a | 26 | uint8_t* buf = const_cast<uint8_t*>(itd->buf); |
va009039 | 9:fecabade834a | 27 | int mps = m_isoEp->m_PacketSize; |
va009039 | 9:fecabade834a | 28 | for(int i = 0; i < fc; i++) { |
va009039 | 9:fecabade834a | 29 | uint16_t psw = itd->OffsetPSW[i]; |
va009039 | 9:fecabade834a | 30 | cc = psw>>12; |
va009039 | 9:fecabade834a | 31 | if (cc == 0 || cc == 9) { |
va009039 | 9:fecabade834a | 32 | int len = psw & 0x7ff; |
va009039 | 9:fecabade834a | 33 | onResult(frame, buf, len); |
va009039 | 9:fecabade834a | 34 | } |
va009039 | 9:fecabade834a | 35 | report_ps_cc_count[cc]++; |
va009039 | 9:fecabade834a | 36 | buf += mps; |
va009039 | 9:fecabade834a | 37 | frame++; |
va009039 | 9:fecabade834a | 38 | } |
va009039 | 9:fecabade834a | 39 | } |
va009039 | 9:fecabade834a | 40 | delete itd; |
va009039 | 9:fecabade834a | 41 | } |
va009039 | 9:fecabade834a | 42 | } |
va009039 | 9:fecabade834a | 43 | |
va009039 | 10:387c49b2fc7e | 44 | USB_TYPE BaseUvc::Control(int req, int cs, int index, uint8_t* buf, int size) |
va009039 | 10:387c49b2fc7e | 45 | { |
va009039 | 10:387c49b2fc7e | 46 | if (req == SET_CUR) { |
va009039 | 10:387c49b2fc7e | 47 | return host->controlWrite(dev, |
va009039 | 10:387c49b2fc7e | 48 | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, |
va009039 | 10:387c49b2fc7e | 49 | req, cs<<8, index, buf, size); |
va009039 | 10:387c49b2fc7e | 50 | } |
va009039 | 10:387c49b2fc7e | 51 | return host->controlRead(dev, |
va009039 | 10:387c49b2fc7e | 52 | USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, |
va009039 | 10:387c49b2fc7e | 53 | req, cs<<8, index, buf, size); |
va009039 | 10:387c49b2fc7e | 54 | } |
va009039 | 10:387c49b2fc7e | 55 | |
va009039 | 10:387c49b2fc7e | 56 | USB_TYPE BaseUvc::setInterfaceAlternate(uint8_t intf, uint8_t alt) |
va009039 | 10:387c49b2fc7e | 57 | { |
va009039 | 10:387c49b2fc7e | 58 | return host->controlWrite(dev, USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE, |
va009039 | 10:387c49b2fc7e | 59 | SET_INTERFACE, alt, intf, NULL, 0); |
va009039 | 10:387c49b2fc7e | 60 | } |
va009039 | 10:387c49b2fc7e | 61 | |
va009039 | 9:fecabade834a | 62 | void BaseUvc::onResult(uint16_t frame, uint8_t* buf, int len) |
va009039 | 9:fecabade834a | 63 | { |
va009039 | 9:fecabade834a | 64 | if(m_pCbItem && m_pCbMeth) |
va009039 | 9:fecabade834a | 65 | (m_pCbItem->*m_pCbMeth)(frame, buf, len); |
va009039 | 9:fecabade834a | 66 | else if(m_pCb) |
va009039 | 9:fecabade834a | 67 | m_pCb(frame, buf, len); |
va009039 | 9:fecabade834a | 68 | } |
va009039 | 9:fecabade834a | 69 | |
va009039 | 9:fecabade834a | 70 | void BaseUvc::setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) ) |
va009039 | 9:fecabade834a | 71 | { |
va009039 | 9:fecabade834a | 72 | m_pCb = pMethod; |
va009039 | 9:fecabade834a | 73 | m_pCbItem = NULL; |
va009039 | 9:fecabade834a | 74 | m_pCbMeth = NULL; |
va009039 | 9:fecabade834a | 75 | } |
va009039 | 9:fecabade834a | 76 | |
va009039 | 9:fecabade834a | 77 | void BaseUvc::clearOnResult() |
va009039 | 9:fecabade834a | 78 | { |
va009039 | 9:fecabade834a | 79 | m_pCb = NULL; |
va009039 | 9:fecabade834a | 80 | m_pCbItem = NULL; |
va009039 | 9:fecabade834a | 81 | m_pCbMeth = NULL; |
va009039 | 9:fecabade834a | 82 | } |
va009039 | 9:fecabade834a | 83 | |
va009039 | 9:fecabade834a | 84 | |
va009039 | 9:fecabade834a | 85 | HCITD::HCITD(BaseEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) { |
va009039 | 9:fecabade834a | 86 | Control = 0xe0000000 | // CC ConditionCode NOT ACCESSED |
va009039 | 9:fecabade834a | 87 | ((FrameCount-1) << 24)| // FC FrameCount |
va009039 | 9:fecabade834a | 88 | TD_DELAY_INT(0) | // DI DelayInterrupt |
va009039 | 9:fecabade834a | 89 | FrameNumber; // SF StartingFrame |
va009039 | 9:fecabade834a | 90 | BufferPage0 = const_cast<uint8_t*>(buf); |
va009039 | 9:fecabade834a | 91 | BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1; |
va009039 | 9:fecabade834a | 92 | Next = NULL; |
va009039 | 9:fecabade834a | 93 | ep = obj; |
va009039 | 9:fecabade834a | 94 | uint32_t addr = reinterpret_cast<uint32_t>(buf); |
va009039 | 9:fecabade834a | 95 | for(int i = 0; i < FrameCount; i++) { |
va009039 | 9:fecabade834a | 96 | uint16_t offset = addr & 0x0fff; |
va009039 | 9:fecabade834a | 97 | if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) { |
va009039 | 9:fecabade834a | 98 | offset |= 0x1000; |
va009039 | 9:fecabade834a | 99 | } |
va009039 | 9:fecabade834a | 100 | OffsetPSW[i] = 0xe000|offset; |
va009039 | 9:fecabade834a | 101 | addr += PacketSize; |
va009039 | 9:fecabade834a | 102 | } |
va009039 | 9:fecabade834a | 103 | } |
va009039 | 9:fecabade834a | 104 | |
va009039 | 9:fecabade834a | 105 | IsochronousEp::IsochronousEp(int addr, uint8_t ep, uint16_t size):BaseEp(addr, ep, size) |
va009039 | 9:fecabade834a | 106 | { |
va009039 | 10:387c49b2fc7e | 107 | ISO_DBG("%p FA:%d EP:%02X MPS:%d\n", this, addr, ep, size); |
va009039 | 9:fecabade834a | 108 | TEST_ASSERT(m_pED); |
va009039 | 9:fecabade834a | 109 | |
va009039 | 9:fecabade834a | 110 | m_pED->Control |= (1 << 15); // F Format ITD |
va009039 | 9:fecabade834a | 111 | |
va009039 | 9:fecabade834a | 112 | TEST_ASSERT(size >= 128 && size <= 1023); |
va009039 | 9:fecabade834a | 113 | m_PacketSize = size; |
va009039 | 9:fecabade834a | 114 | m_FrameCount = 4; // 1-8 |
va009039 | 9:fecabade834a | 115 | TEST_ASSERT(m_FrameCount >= 1 && m_FrameCount <= 8); |
va009039 | 9:fecabade834a | 116 | m_itd_queue_count = 0; |
va009039 | 9:fecabade834a | 117 | reset(); |
va009039 | 9:fecabade834a | 118 | HCITD* itd = new_HCITD(this); |
va009039 | 9:fecabade834a | 119 | m_pED->TailTd = reinterpret_cast<HCTD*>(itd); |
va009039 | 9:fecabade834a | 120 | m_pED->HeadTd = reinterpret_cast<HCTD*>(itd); |
va009039 | 9:fecabade834a | 121 | TEST_ASSERT(itd); |
va009039 | 9:fecabade834a | 122 | if (itd == NULL) { |
va009039 | 9:fecabade834a | 123 | return; |
va009039 | 9:fecabade834a | 124 | } |
va009039 | 9:fecabade834a | 125 | _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA); |
va009039 | 9:fecabade834a | 126 | TEST_ASSERT(hcca); |
va009039 | 9:fecabade834a | 127 | if (hcca == NULL) { |
va009039 | 9:fecabade834a | 128 | return; |
va009039 | 9:fecabade834a | 129 | } |
va009039 | 10:387c49b2fc7e | 130 | hcca->enqueue(m_pED); |
va009039 | 9:fecabade834a | 131 | } |
va009039 | 9:fecabade834a | 132 | |
va009039 | 9:fecabade834a | 133 | void IsochronousEp::reset(int delay_ms) |
va009039 | 9:fecabade834a | 134 | { |
va009039 | 9:fecabade834a | 135 | m_FrameNumber = LPC_USB->HcFmNumber + delay_ms; |
va009039 | 9:fecabade834a | 136 | } |
va009039 | 9:fecabade834a | 137 | |
va009039 | 9:fecabade834a | 138 | HCITD* IsochronousEp::new_HCITD(BaseEp* obj) |
va009039 | 9:fecabade834a | 139 | { |
va009039 | 9:fecabade834a | 140 | HCITD* itd = new(m_PacketSize*m_FrameCount)HCITD(obj, m_FrameNumber, m_FrameCount, m_PacketSize); |
va009039 | 9:fecabade834a | 141 | if (itd == NULL) { |
va009039 | 9:fecabade834a | 142 | return NULL; |
va009039 | 9:fecabade834a | 143 | } |
va009039 | 9:fecabade834a | 144 | m_FrameNumber += m_FrameCount; |
va009039 | 9:fecabade834a | 145 | return itd; |
va009039 | 9:fecabade834a | 146 | } |
va009039 | 9:fecabade834a | 147 | |
va009039 | 10:387c49b2fc7e | 148 | HCITD* IsochronousEp::isochronousReceive(int millisec) |
va009039 | 9:fecabade834a | 149 | { |
va009039 | 9:fecabade834a | 150 | TEST_ASSERT(m_itd_queue_count >= 0); |
va009039 | 9:fecabade834a | 151 | while(m_itd_queue_count < 3 && m_itd_queue_count < HCTD_QUEUE_SIZE) { |
va009039 | 9:fecabade834a | 152 | HCITD* itd = reinterpret_cast<HCITD*>(m_pED->TailTd); |
va009039 | 9:fecabade834a | 153 | TEST_ASSERT(itd); |
va009039 | 9:fecabade834a | 154 | if (itd == NULL) { |
va009039 | 9:fecabade834a | 155 | return NULL; |
va009039 | 9:fecabade834a | 156 | } |
va009039 | 9:fecabade834a | 157 | HCITD* blank_itd = new_HCITD(this); |
va009039 | 9:fecabade834a | 158 | TEST_ASSERT(blank_itd); |
va009039 | 9:fecabade834a | 159 | if (blank_itd == NULL) { |
va009039 | 9:fecabade834a | 160 | return NULL; |
va009039 | 9:fecabade834a | 161 | } |
va009039 | 9:fecabade834a | 162 | itd->Next = blank_itd; |
va009039 | 9:fecabade834a | 163 | m_pED->TailTd = reinterpret_cast<HCTD*>(blank_itd); |
va009039 | 9:fecabade834a | 164 | m_itd_queue_count++; |
va009039 | 9:fecabade834a | 165 | //DBG_IED(m_pED); |
va009039 | 9:fecabade834a | 166 | enable(); // Enable Periodic |
va009039 | 9:fecabade834a | 167 | } |
va009039 | 9:fecabade834a | 168 | |
va009039 | 9:fecabade834a | 169 | HCITD* itd = get_queue_HCITD(millisec); |
va009039 | 9:fecabade834a | 170 | if (itd) { |
va009039 | 9:fecabade834a | 171 | m_itd_queue_count--; |
va009039 | 9:fecabade834a | 172 | } |
va009039 | 9:fecabade834a | 173 | return itd; |
va009039 | 9:fecabade834a | 174 | } |
va009039 | 9:fecabade834a | 175 | |
va009039 | 9:fecabade834a | 176 | HCITD* IsochronousEp::get_queue_HCITD(int millisec) |
va009039 | 9:fecabade834a | 177 | { |
va009039 | 9:fecabade834a | 178 | for(int i = 0; i < 16; i++) { |
va009039 | 9:fecabade834a | 179 | osEvent evt = m_queue.get(millisec); |
va009039 | 9:fecabade834a | 180 | if (evt.status == osEventMessage) { |
va009039 | 9:fecabade834a | 181 | HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p); |
va009039 | 9:fecabade834a | 182 | TEST_ASSERT(itd); |
va009039 | 9:fecabade834a | 183 | return itd; |
va009039 | 9:fecabade834a | 184 | } else if (evt.status == osOK) { |
va009039 | 9:fecabade834a | 185 | continue; |
va009039 | 9:fecabade834a | 186 | } else if (evt.status == osEventTimeout) { |
va009039 | 9:fecabade834a | 187 | return NULL; |
va009039 | 9:fecabade834a | 188 | } else { |
va009039 | 10:387c49b2fc7e | 189 | ISO_DBG("evt.status: %02x\n", evt.status); |
va009039 | 9:fecabade834a | 190 | TEST_ASSERT(evt.status == osEventMessage); |
va009039 | 9:fecabade834a | 191 | return NULL; |
va009039 | 9:fecabade834a | 192 | } |
va009039 | 9:fecabade834a | 193 | } |
va009039 | 9:fecabade834a | 194 | return NULL; |
va009039 | 9:fecabade834a | 195 | } |
va009039 | 9:fecabade834a | 196 | |
va009039 | 9:fecabade834a | 197 | void IsochronousEp::enable() |
va009039 | 9:fecabade834a | 198 | { |
va009039 | 9:fecabade834a | 199 | LPC_USB->HcControl |= OR_CONTROL_PLE; |
va009039 | 9:fecabade834a | 200 | } |
va009039 | 9:fecabade834a | 201 | |
va009039 | 10:387c49b2fc7e | 202 | void IsochronousEp::disconnect() |
va009039 | 10:387c49b2fc7e | 203 | { |
va009039 | 10:387c49b2fc7e | 204 | m_pED->setSkip(); |
va009039 | 10:387c49b2fc7e | 205 | ISO_DBG("m_itd_queue_count: %d", m_itd_queue_count); |
va009039 | 10:387c49b2fc7e | 206 | Timer t; |
va009039 | 10:387c49b2fc7e | 207 | t.reset(); |
va009039 | 10:387c49b2fc7e | 208 | t.start(); |
va009039 | 10:387c49b2fc7e | 209 | while(m_itd_queue_count > 0 && t.read_ms() <= (8*3)) { |
va009039 | 10:387c49b2fc7e | 210 | HCITD* itd = get_queue_HCITD(0); |
va009039 | 10:387c49b2fc7e | 211 | if (itd) { |
va009039 | 10:387c49b2fc7e | 212 | ISO_DBG("ITD: %p", itd); |
va009039 | 10:387c49b2fc7e | 213 | delete itd; |
va009039 | 10:387c49b2fc7e | 214 | m_itd_queue_count--; |
va009039 | 10:387c49b2fc7e | 215 | t.reset(); |
va009039 | 10:387c49b2fc7e | 216 | } |
va009039 | 10:387c49b2fc7e | 217 | } |
va009039 | 10:387c49b2fc7e | 218 | ISO_DBG("m_itd_queue_count: %d, t_ms: %d", m_itd_queue_count, t.read_ms()); |
va009039 | 10:387c49b2fc7e | 219 | HCITD* head = reinterpret_cast<HCITD*>(reinterpret_cast<uint32_t>(m_pED->HeadTd)&~3); // delete Halted and Toggle Carry bit |
va009039 | 10:387c49b2fc7e | 220 | TEST_ASSERT(head); |
va009039 | 10:387c49b2fc7e | 221 | HCITD* tail = reinterpret_cast<HCITD*>(m_pED->TailTd); |
va009039 | 10:387c49b2fc7e | 222 | TEST_ASSERT(tail); |
va009039 | 10:387c49b2fc7e | 223 | while(head != tail) { |
va009039 | 10:387c49b2fc7e | 224 | HCITD* next = head->Next; |
va009039 | 10:387c49b2fc7e | 225 | TEST_ASSERT(next); |
va009039 | 10:387c49b2fc7e | 226 | ISO_DBG("ED ITD:%p next:%p", head, next); |
va009039 | 10:387c49b2fc7e | 227 | delete head; |
va009039 | 10:387c49b2fc7e | 228 | TEST_ASSERT(m_itd_queue_count > 0); |
va009039 | 10:387c49b2fc7e | 229 | m_itd_queue_count--; |
va009039 | 10:387c49b2fc7e | 230 | head = next; |
va009039 | 10:387c49b2fc7e | 231 | } |
va009039 | 10:387c49b2fc7e | 232 | TEST_ASSERT(m_itd_queue_count == 0); |
va009039 | 10:387c49b2fc7e | 233 | delete head; |
va009039 | 10:387c49b2fc7e | 234 | |
va009039 | 10:387c49b2fc7e | 235 | _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA); |
va009039 | 10:387c49b2fc7e | 236 | TEST_ASSERT(hcca); |
va009039 | 10:387c49b2fc7e | 237 | hcca->dequeue(m_pED); |
va009039 | 10:387c49b2fc7e | 238 | delete m_pED; |
va009039 | 10:387c49b2fc7e | 239 | } |
va009039 | 10:387c49b2fc7e | 240 | |
va009039 | 9:fecabade834a | 241 | BaseEp::BaseEp(int addr, uint8_t ep, uint16_t size, int lowSpeed):m_td_queue_count(0) |
va009039 | 9:fecabade834a | 242 | { |
va009039 | 10:387c49b2fc7e | 243 | ISO_DBG("%p FA=%d EN=%02x MPS=%d S=%d\n", this, addr, ep, size, lowSpeed); |
va009039 | 9:fecabade834a | 244 | TEST_ASSERT(size >= 8 && size <= 1023); |
va009039 | 9:fecabade834a | 245 | TEST_ASSERT(lowSpeed == 0 || lowSpeed == 1); |
va009039 | 9:fecabade834a | 246 | m_pED = new _HCED(addr, ep, size, lowSpeed); |
va009039 | 9:fecabade834a | 247 | TEST_ASSERT(m_pED); |
va009039 | 9:fecabade834a | 248 | } |