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.
Fork of USBHostC270_example by
USBHostC270/USBisochronous/USBIsochronous.h
- Committer:
- chalikias
- Date:
- 2015-05-21
- Revision:
- 14:449f809d07eb
- Parent:
- 12:ea4badc78215
File content as of revision 14:449f809d07eb:
// USBIsochronous.h
#pragma once
class IsochronousEp;
struct HCITD { // HostController Isochronous Transfer Descriptor
__IO uint32_t Control; // +0 Transfer descriptor control
uint8_t* BufferPage0; // +4 Buffer Page 0
HCITD* Next; // +8 Physical pointer to next Isochronous Transfer Descriptor
uint8_t* BufferEnd; // +12 buffer End
__IO uint16_t OffsetPSW[8]; // +16 Offset/PSW
IsochronousEp* ep; // +32 endpoint object
__IO uint8_t buf[0]; // +36 buffer
// +36
HCITD(IsochronousEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize);
inline void* operator new(size_t size, int buf_size) {
void* p;
if (posix_memalign(&p, 32, size+buf_size) == 0) {
return p;
}
return NULL;
}
inline void operator delete(void* p) {
free(p);
}
inline uint16_t StartingFrame() {
return Control & 0xffff;
}
inline uint8_t FrameCount() {
return ((Control>>24)&7)+1;
}
inline uint8_t ConditionCode() {
return Control>>28;
}
};
struct _HCED { // HostController EndPoint Descriptor
__IO uint32_t Control; // +0 Endpoint descriptor control
HCTD* TailTd; // +4 Physical address of tail in Transfer descriptor list
__IO HCTD* HeadTd; // +8 Physcial address of head in Transfer descriptor list
_HCED* Next; // +12 Physical address of next Endpoint descriptor
// +16
_HCED(int addr, uint8_t ep, uint16_t size, int lowSpeed = 0) {
Control = addr | /* USB address */
((ep & 0x7F) << 7) | /* Endpoint address */
(ep!=0?(((ep&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */
((lowSpeed?1:0) << 13) | /* speed full=0 low=1 */
(size << 16); /* MaxPkt Size */
Next = NULL;
}
inline void* operator new(size_t size) {
void* p;
if (posix_memalign(&p, 16, size) == 0) {
return p;
}
return NULL;
}
inline void operator delete(void* p) {
free(p);
}
inline uint8_t FunctionAddress() {
return Control & 0x7f;
}
inline int Speed() {
return (Control>>13)&1;
}
inline void setFunctionAddress(int addr) {
Control &= ~0x7f;
Control |= addr;
}
inline void setMaxPacketSize(uint16_t size) {
Control &= ~0xffff0000;
Control |= size<<16;
}
int Skip() {
return (Control>>14) & 1;
}
void setSkip() {
Control |= (1<<14);
}
void setFormat() {
Control |= (1<<15);
}
template<typename T>
inline bool enqueue(T* td) {
if (td) {
T* tail = reinterpret_cast<T*>(TailTd);
if (tail) {
tail->Next = td;
TailTd = reinterpret_cast<HCTD*>(td);
return true;
}
}
return false;
}
template<typename T>
inline T* dequeue() {
T* head = reinterpret_cast<T*>(reinterpret_cast<uint32_t>(HeadTd)&~3); // delete Halted and Toggle Carry bit
T* tail = reinterpret_cast<T*>(TailTd);
if (head == NULL || tail == NULL || head == tail) {
return NULL;
}
HeadTd = reinterpret_cast<HCTD*>(head->Next);
return head;
}
template<typename T>
void init_queue(T* td) {
TailTd = reinterpret_cast<HCTD*>(td);
HeadTd = reinterpret_cast<HCTD*>(td);
}
};
struct _HCCA { // Host Controller Communication Area
_HCED* InterruptTable[32]; // +0 Interrupt Table
__IO uint16_t FrameNumber;// +128 Frame Number
__IO uint16_t Pad1; // +130
__IO HCTD* DoneHead; // +132 Done Head
uint8_t Reserved[116]; // +136 Reserved for future use
uint8_t Unknown[4]; // +252 Unused
// +256
inline void* operator new(size_t size) {
void* p;
if (posix_memalign(&p, 256, size) == 0) {
return p;
}
return NULL;
}
inline void operator delete(void* p) {
free(p);
}
inline void enqueue(_HCED* ed) {
for(int i = 0; i < 32; i++) {
if (InterruptTable[i] == NULL) {
InterruptTable[i] = ed;
} else {
_HCED* nextEd = InterruptTable[i];
while(nextEd->Next && nextEd->Next != ed) {
nextEd = nextEd->Next;
}
nextEd->Next = ed;
}
}
}
inline void dequeue(_HCED* ed) {
for(int i = 0; i < 32; i++) {
if (InterruptTable[i] == ed) {
InterruptTable[i] = ed->Next;
} else if (InterruptTable[i]) {
_HCED* nextEd = InterruptTable[i];
while(nextEd) {
if (nextEd->Next == ed) {
nextEd->Next = ed->Next;
break;
}
nextEd = nextEd->Next;
}
}
}
}
};
#define HCITD_QUEUE_SIZE 3
class IsochronousEp {
public:
void init(int addr, uint8_t ep, uint16_t size, uint8_t frameCount = 4, uint8_t queueLimit = HCITD_QUEUE_SIZE);
void reset(int delay_ms = 100);
HCITD* isochronousReceive(int timeout_ms);
int isochronousSend(uint8_t* buf, int len, int timeout_ms);
HCITD* get_queue_HCITD(int timeout_ms);
uint16_t m_PacketSize;
void disconnect();
void irqWdhHandler(HCITD* itd) {m_queue.put(itd);} // WDH
private:
HCITD* new_HCITD(IsochronousEp* obj);
Queue<HCITD, HCITD_QUEUE_SIZE> m_queue; // ITD done queue
int m_itd_queue_count;
int m_itd_queue_limit;
uint16_t m_FrameNumber;
int m_FrameCount; // 1-8
void enable();
_HCED* m_pED;
};
