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.
Dependencies: FatFileSystem TB6612FNG2 mbed
uvc/uvc.cpp
- Committer:
- mbed_Cookbook_SE
- Date:
- 2015-11-30
- Revision:
- 0:de03cbbcd0ff
File content as of revision 0:de03cbbcd0ff:
#include "mbed.h"
#include "uvc.h"
//#define __DEBUG
//#define __DEBUG3
#include "mydbg.h"
#include "usb_itd.h"
uvc::uvc(int cam)
{
DBG("cam=%d\n", cam);
DBG_ASSERT(cam >= 0);
m_cam = cam;
m_init = false;
m_connect = false;
m_int_seq = 0;
m_iso_seq = 0;
m_width = 0;
m_height = 0;
m_payload = PAYLOAD_MJPEG;
m_FormatIndex = 0;
m_FrameIndex = 0;
m_FrameInterval = 0;
m_PacketSize = 0;
m_stream = NULL;
for(int i = 0; i <= 15; i++) {
ReportConditionCode[i] = 0;
}
clearOnResult();
}
uvc::~uvc()
{
clearOnResult();
}
int uvc::setup()
{
if (!m_init) {
return _init();
}
return 0;
}
int uvc::get_jpeg(const char* path)
{
const int size = 4800;
const int timeout = 5000;
uint8_t* buf = new uint8_t[size];
DBG_ASSERT(buf);
if (buf == NULL) {
return -1;
}
usb_mjpeg mjpeg(buf, size);
attach(&mjpeg);
Timer t;
t.reset();
t.start();
while(t.read_ms() < timeout) {
int stat = isochronous();
if (mjpeg.status() >= 0) {
break;
}
}
detach();
int len = mjpeg.status();
if (len >= 0) {
if (path != NULL) {
FILE *fp = fopen(path, "wb");
if (fp != NULL) {
for(int i = 0; i < len; i++) {
fputc(buf[i], fp);
}
fclose(fp);
}
}
}
delete[] buf;
return len;
}
int uvc::get_jpeg(uint8_t* buf, int size)
{
//DBG("buf=%p size=%d\n", buf, size);
const int timeout = 5000;
usb_mjpeg mjpeg(buf, size);
attach(&mjpeg);
Timer t;
t.reset();
t.start();
while(t.read_ms() < timeout) {
int stat = isochronous();
if (mjpeg.status() >= 0) {
break;
}
}
detach();
int len = mjpeg.status();
return len;
}
bool uvc::interrupt()
{
if (!m_init) {
_init();
}
if (m_int_seq == 0) {
int rc = m_pEpIntIn->transfer(m_int_buf, sizeof(m_int_buf));
if (rc != USBERR_PROCESSING) {
return false;
}
m_int_seq++;
}
int len = m_pEpIntIn->status();
if (len > 0) {
m_int_seq = 0;
DBG_BYTES("interrupt", m_int_buf, len);
return true;
}
return false;
}
#define CC_NOERROR 0x0
#define CC_DATAOVERRUN 0x8
#define CC_DATAUNDERRUN 0x9
inline void DI()
{
NVIC_DisableIRQ(USB_IRQn);
}
inline void EI()
{
NVIC_EnableIRQ(USB_IRQn);
}
int uvc::isochronous()
{
if (m_iso_seq == 0) {
uint16_t frame = LPC_USB->HcFmNumber;
m_iso_frame = frame + 10; // 10msec
DBG_ASSERT(m_pEpIsoIn->m_itdActive == 0);
m_iso_seq++;
}
if (m_iso_seq == 1) {
DBG_ASSERT(m_itdCount > 0 && m_itdCount <= 8);
while(m_pEpIsoIn->m_itdActive < m_itdCount) {
int len = m_PacketSize * m_FrameCount;
uint8_t* buf = (uint8_t*)usb_get_bp(len);
if (buf == NULL) {
DBG("len=%d\n", len);
DBG("m_itdCount=%d\n", m_itdCount);
}
DBG_ASSERT(buf);
int rc = m_pEpIsoIn->transfer(m_iso_frame, m_FrameCount, buf, len);
m_iso_frame += m_FrameCount;
DBG_ASSERT(rc == USBERR_PROCESSING);
}
m_iso_seq++;
}
if (m_iso_seq == 2) {
//DBG("frame:%04X\n", LPC_USB->HcFmNumber);
while(1) {
DI();
bool empty = m_pEpIsoIn->queue_done_itd.empty();
EI();
if (empty) {
break;
}
DI();
HCITD* itd = m_pEpIsoIn->queue_done_itd.front();
m_pEpIsoIn->queue_done_itd.pop();
EI();
m_pEpIsoIn->m_itdActive--;
usb_itd iso_td(itd);
//DBG("frame:%04X\n", LPC_USB->HcFmNumber);
//DBG("itd->Control=%08X\n", itd->Control);
int cc = iso_td.ConditionCode();
DBG_ASSERT(cc >= 0 && cc <= 15);
ReportConditionCode[cc]++;
if (cc != CC_NOERROR) {
DBG3("%04X ERR:%X\n", LPC_USB->HcFmNumber, cc);
iso_td.free();
m_iso_seq = 3;
return -1;
}
uint16_t frame = iso_td.StartingFrame();
int fc = iso_td.FrameCount();
for(int i = 0; i < fc; i++) {
int len = iso_td.Length(i);
if (len > 0) {
if (m_stream) {
m_stream->input(frame+i, iso_td.BufferPage(i, m_PacketSize), len);
}
onResult(frame+i, iso_td.BufferPage(i, m_PacketSize), len);
}
}
iso_td.free();
}
//DBG("frame:%04X\n", LPC_USB->HcFmNumber);
m_iso_seq = 1;
return m_pEpIsoIn->m_itdActive;
}
if (m_iso_seq == 3) { // cleanup
DBG("m_pEpIsoIn->queue_done_itd.size() :%d\n", m_pEpIsoIn->queue_done_itd.size());
while(1) {
DI();
bool empty = m_pEpIsoIn->queue_done_itd.empty();
EI();
if (empty) {
break;
}
DI();
HCITD* itd = m_pEpIsoIn->queue_done_itd.front();
m_pEpIsoIn->queue_done_itd.pop();
EI();
m_pEpIsoIn->m_itdActive--;
usb_itd iso_td(itd);
iso_td.free();
}
if (m_pEpIsoIn->m_itdActive == 0) {
m_iso_seq = 0;
}
}
return m_pEpIsoIn->m_itdActive;
}
void uvc::attach(usb_stream* stream)
{
m_stream = stream;
}
void uvc::detach()
{
m_stream = NULL;
}
void uvc::onResult(uint16_t frame, uint8_t* buf, int len)
{
if(m_pCbItem && m_pCbMeth)
(m_pCbItem->*m_pCbMeth)(frame, buf, len);
else if(m_pCb)
m_pCb(frame, buf, len);
}
void uvc::setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) )
{
m_pCb = pMethod;
m_pCbItem = NULL;
m_pCbMeth = NULL;
}
void uvc::clearOnResult()
{
m_pCb = NULL;
m_pCbItem = NULL;
m_pCbMeth = NULL;
}