Tuesday, June 18, 2019

OpenSource DIY USB Webcam: OV7670 OV2640 Interfacing With PIC32MZ Streaming Video over USB Video Device class UVC Device

This project is going to extension to my previous project in which i implemented USB Video device class onto Microchip PIC32 USB stack.  Last project i showed how once can transmit static image over USB UVC , now i will be showing you how you can interface these commonly available  VGA/UXGA Sensors OV7670/OV2640 to PIC32MZ MCU.


I have Implemented and tested USB stack first with PIC32MX470F512H , as you may already know PIC32MX MCU have only USB FS , which gives you only 12Mbit per second around ~ 1.5 MByte per-second bus bandwidth, and ultimate payload bandwidth is going to be somewhat less than 1.1MByte/s depending on how exactly you transfer payload.

with USB Isochronous endpoint , only one transfer of 1023 byte is allowed per millisecond , which translates to only ~1Mbyte per second.

UVC support only a few formats, i am using YUV format as both of the camera module directly output YUV data. YUV format need 4 byte per 2 pixel , so for a 100x100 pixel wide image , you will need 100x100x2 bytes --> 20Kbytes .
YUV is uncompressed format, so 1Mbyte per-second bandwidth really become tight for any serious use.

Although UVC also support MJPEG , but issue is OV7670 does not directly output JPEG, and i have not yet implemented mjpeg encoder in firmware, on the other hand OV2640 does output jpeg.

so here the first Setup connections block diagram with PIC32MX

With PIC32MX i have used Parallel Master port of PIC32 , PMP is configured as PMP Slave , VSYNC connected to INT1 to sync whole buffering and transmission over USB.
HSYNC of camera is connected to PMP Chip select pin which Masks PMP Write pin, PMP Write pin connected to Pixel clock , on the transaction of Pixel clock while PMPCS (HSYNC) is activated , data get latched into PMP Data register.

Write to PMPDIN register after data get latched trigger DMA , DMA copy data from PMPDIN register to buffer, buffer is used by Application task to transfer over USB.

PIC32MZ2048EFM064 Hardware

Here is the schematic of PIC32MZ hardware

Test Video


PCB Source and Gerber are available in my github repo

As PIC32MZ have USB HS , with 480Mbit/s this was direct advantage of very high speed data rate, with usb  Isochronous , there are total 3 , 1024 byte transfers are allowed per 125uS, which results to ~24Mbyte per second, with 24MBps usb bandwidth is certainly not going to be issue with VGA resolution.
There were Certain limitation in PIC32MZ as well, this limitation caused by silicon bug present in PMP slave mode , interrupt bit of PMP is permanently set , which makes DMA unusable.
so i changed block diagram.

same as before VSYNC is connected to interrupt, but now HSYNC from camera is not used at all and PCLK directly trigger a DMA which reads directly from PORTE , which is configured as simple 8bit GPIO input. This setup lack PMP buffers (if used is advanced slave mode).
PCLK is connected to an interrupt but no isr is implemented as PCLK is quite fast signal ~8MHz for VGA @10FPS, if you implement ISR , it may not be able to coupe up at 8Mhz trigger rate.

One Complete Frame Captured and Transmitted over USB
Start of single Frame

Single Line , one HSYNC Transfer

VLC Streaming video from PIC32MZ 640x480 @10FPS

640x480 VGA Image OV7670 @10FPS

Firmware Source 

Firmware source PCB files and other Documents are available in my GitHub account repo



  1. This comment has been removed by the author.

    1. which option should select (harmony or standard)?. Where do have to paste code file you have shared.

    2. It does not use any harmony code, Create a mplab x project including all the files and that is it.

    3. Thanks for the reply. I'm noob I know that I have too much to learn in mplabx. But I did something.

      1st thing I did Created project in standalone and I collected all files and put all .h files(2000+) in header files and .c (80+) and .s (1) file in source files and while building it did not work.

      2nd thing I did was created standalone project and put main.c and app.c in source files, app.h in header files and system_config folder put in Important files and while building it still did not work.

      And to try other I did not get any option to include all files and run