Simple USBHost WebCam for EA LPC4088 QSB/LPC1768 test program

Dependencies:   LPC4088-USBHost mbed

EA LPC4088 QSB/LPC1768をUSBホストにしてWebカメラからJPEG画像を読み取るテストプログラムです。

The usage is the same as KL46Z-USBHostC270_example.
使い方はKL46Z-USBHostC270_exampleと同じです。
動作確認: Logitech C270,Logitech Q200R(Qcam Orbit AF)
/media/uploads/va009039/lpc4088-c270-480x360.jpg

LPC4088-USBHostC270/USBIsochronous.cpp

Committer:
va009039
Date:
2014-04-25
Revision:
1:1bb68ef9aa77
Parent:
0:c972ee42b455

File content as of revision 1:1bb68ef9aa77:

// USBIsochronous.cpp
#include "USBHostConf.h"
#include "USBHost.h"
#include "USBIsochronous.h"

//#define ISO_DEBUG 1
#ifdef ISO_DEBUG
#define ISO_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define ISO_DBG(...)  while(0);
#endif

#if 0
#define TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
#else
#define TEST_ASSERT(A) while(0)
#endif

IsochronousEp::IsochronousEp(USBDeviceConnected* dev):USBEndpoint(dev) {
}

void IsochronousEp::init2(uint8_t frameCount, uint8_t queueLimit) {
    m_pED  = new HCED(this);
    m_pED->setFormat(); // F Format ITD
    TEST_ASSERT(frameCount >= 1 && frameCount <= 8);
    m_FrameCount = frameCount;
    TEST_ASSERT(queueLimit >= 1 && queueLimit <= HCTD_QUEUE_SIZE);
    m_itd_queue_limit = queueLimit;
    
    m_itd_queue_count = 0;
    reset();
    HCITD* itd = new_HCITD(this);
    m_pED->init_queue(reinterpret_cast<HCTD*>(itd)); 
    HCCA* hcca = reinterpret_cast<HCCA*>(LPC_USB->HcHCCA);
    hcca->enqueue(m_pED);
}

void IsochronousEp::reset(int delay_ms) {
    m_FrameNumber = LPC_USB->HcFmNumber + delay_ms;
}

HCITD* IsochronousEp::new_HCITD(IsochronousEp* obj) {
    HCITD* itd = new(getSize() * m_FrameCount)HCITD(obj, m_FrameNumber, m_FrameCount, getSize());
    m_FrameNumber += m_FrameCount;
    return itd;
}

HCITD* IsochronousEp::isochronousReceive(int timeout_ms) {
    while(m_itd_queue_count < m_itd_queue_limit) {
        HCITD* blank_itd = new_HCITD(this);
        if (m_pED->enqueue(reinterpret_cast<HCTD*>(blank_itd))) {
            m_itd_queue_count++;
        }
        enable(); // Enable Periodic
    }
    
    HCITD* itd = get_queue_HCITD(timeout_ms);
    if (itd) {
        m_itd_queue_count--;
    }
    return itd;
}

#if 0
int IsochronousEp::isochronousSend(uint8_t* buf, int len, int timeout_ms)
{
    //ISO_DBG("buf: %p, len: %d", buf, len);
    HCITD* itd = get_queue_HCITD(timeout_ms);
    if (itd) {
        delete itd;
        m_itd_queue_count--;
        TEST_ASSERT(m_itd_queue_count >= 0);
    }
    TEST_ASSERT(m_itd_queue_count >= 0);
    if(m_itd_queue_count < m_itd_queue_limit) {
        if (m_pED == NULL) {
            ISO_DBG("m_pED is NULL");
            return 0;
        }
        if (m_pED->Skip()) {
            return 0;
        }
        itd = new_HCITD(this);
        TEST_ASSERT(itd);
        //ISO_DBG("m_pED: %p itd: %p", m_pED, itd);
        memcpy(const_cast<uint8_t*>(itd->buf), buf, len);
        if (m_pED->enqueue<HCITD>(itd)) {
            m_itd_queue_count++;
        }
        enable(); // Enable Periodic
        //ISO_DBG("m_itd_queue_count: %d", m_itd_queue_count);
        return len;
    }
    return 0;
}
#endif

HCITD* IsochronousEp::get_queue_HCITD(int timeout_ms)
{
    Timer t;
    t.reset();
    t.start();
    do {
        osEvent evt = m_queue.get(0);
        if (evt.status == osEventMessage) {
            HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p);
            TEST_ASSERT(itd);
            return itd;
        } else if (evt.status == osOK) {
            ;
        } else if (evt.status == osEventTimeout) {
            break;
        } else {
            ISO_DBG("evt.status: %02x\n", evt.status);
            TEST_ASSERT(evt.status == osEventMessage);
            break;
        }
    } while(t.read_ms() < timeout_ms);
    return NULL;
}

void IsochronousEp::enable()
{
    LPC_USB->HcControl |= OR_CONTROL_PLE;
}