VC0706 driver for radio shack camera shield

Dependencies:   MODSERIAL

Sample Code

#include "mbed.h"
#include "SDFileSystem.h"
#include "CameraShield.h"
#include <stdio.h>


unsigned char VC0706_rx_buffer[80];
    

SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd", PTE6, SDFileSystem::SWITCH_POS_NO, 25000000); // MOSI, MISO, SCLK, SSEL
CameraShield camera(PTC17, PTC16);


void CapturePhoto()
{
    uint32_t    frame_length = camera.VC0706_get_frame_buffer_length();        //get frame buffer length
    uint32_t    vc_frame_address = READ_DATA_BLOCK_NO;    
        
    FILE* camFile = fopen("/sd/temp.jpg", "w");
        
    while(vc_frame_address<frame_length)
    {   
        camera.VC0706_read_frame_buffer(vc_frame_address - READ_DATA_BLOCK_NO, READ_DATA_BLOCK_NO);
        wait_ms(9);

        //get the data with length=READ_DATA_BLOCK_NObytes 
        camera.buffer_read(VC0706_rx_buffer, 80);

        // write data to temp.jpg
        fwrite(VC0706_rx_buffer + 5, sizeof(char), READ_DATA_BLOCK_NO, camFile);
    
        //read next READ_DATA_BLOCK_NO bytes from frame buffer
        vc_frame_address = vc_frame_address + READ_DATA_BLOCK_NO;
    }

    // get the last data
    vc_frame_address = vc_frame_address - READ_DATA_BLOCK_NO;
    uint32_t last_data_length = frame_length - vc_frame_address;
    
    camera.VC0706_read_frame_buffer(vc_frame_address, last_data_length);
    wait_ms(9);
    //get the data 
    camera.buffer_read(VC0706_rx_buffer, 80);
            
    fwrite(VC0706_rx_buffer+5, sizeof(char), last_data_length, camFile);
    
    fclose(camFile);
}

 
int main (void) 
{                      
    // Check to see if the file exists: 
    // if exists,delete the file:
    sd.remove("/sd/temp.jpg");
    
    camera.Init();  
    camera.VC0706_image_size(VC0706_640x480);
    camera.ResumeVideo();   
    wait_ms(500);   
    
    
    while(1)
    {
        camera.ResumeVideo();   
        wait_ms(1000);
        
        camera.TakeSnapShot();
        CapturePhoto(); 
    }
}
Revision:
0:e5fc19091502
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CameraShield.cpp	Thu Dec 18 04:35:50 2014 +0000
@@ -0,0 +1,568 @@
+/*****************************************************************************************
+** File: CameraShield.cpp                                                               **
+**                                                                                      **
+** For radio shack Camera Shield.                                                       **
+** http://blog.radioshack.com/2013/01/radioshack-camera-shield-for-arduino-boards/      **
+*****************************************************************************************/
+
+#include "CameraShield.h"
+
+
+CameraShield::CameraShield ( PinName tx, PinName rx, int speed ) : _serial(tx, rx)
+{
+    _serial.baud(speed);   
+}
+
+
+void CameraShield::Init()
+{      
+    VC0706_compression_ratio(63);
+    wait_ms(100);
+
+    VC0706_frame_control(3);
+    wait_ms(10);
+}
+
+
+void CameraShield::TakeSnapShot()
+{
+    VC0706_frame_control(0);
+    wait_ms(10);
+        _serial.rxBufferFlush();
+}
+
+
+void CameraShield::ResumeVideo()
+{
+    VC0706_frame_control(3);
+    wait_ms(10);
+        _serial.rxBufferFlush();
+}
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_reset
+ * Description    : Reset VC0706
+ *                  
+ * Input          : None
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_reset(void)
+{
+    unsigned char   tx_vcbuffer[4];
+        
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_RESET;
+    tx_vcbuffer[3]=0x00;
+
+    buffer_send(tx_vcbuffer, 4);
+}
+
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_get_version
+ * Description    : Request version string from VC0706
+ *                  
+ * Input          : None
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_get_version()
+{
+    unsigned char   tx_vcbuffer[4];
+    
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_GEN_VERSION;
+    tx_vcbuffer[3]=0x00;
+    
+    buffer_send(tx_vcbuffer, 4);
+}
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_tv_out_control
+ * Description    : stop or start TV output from VC0706
+ *                  
+ * Input          : on=0 stop tv output
+ ;          :  on=1 start tv output
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_tv_out_control(int on)
+{
+    unsigned char   tx_vcbuffer[5];
+    
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_TV_OUT_CTRL;
+    tx_vcbuffer[3]=0x01;
+    tx_vcbuffer[4]=on;
+
+    buffer_send(tx_vcbuffer, 5);
+}
+
+/*******************************************************************************
+ * Function Name  : VC0706_osd_add_char
+ * Description    : ADD OSD CHARACTERS TO CHANNELS(CHANNEL 1)
+ *                  
+ * Input          : col : Display column
+ *  `         row: Display Row
+ *            osd_string : display string (max 14 characters)
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_osd_add_char(int col, int row, char * osd_string)
+{
+    unsigned char   tx_vcbuffer[80];
+    unsigned char col_row;
+    int string_length;
+    int i;
+    
+    col&=0x0f;
+    row&=0x0f;
+    col_row=(unsigned char)(col<<4 | row);
+
+    string_length=strlen(osd_string);
+    if (string_length>14)
+        string_length=14;       // max 14 osd characters
+    
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_OSD_ADD_CHAR;
+    tx_vcbuffer[3]=string_length+2;     
+    tx_vcbuffer[4]=string_length;       // character number
+    tx_vcbuffer[5]=col_row;                 
+
+    for (i=0;i<string_length;i++)
+    {
+        tx_vcbuffer[i+6]=osd_string[i];
+    }
+    
+
+    buffer_send(tx_vcbuffer, string_length+6);
+}
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_w_h_downsize
+ * Description    : control width and height downsize attribute
+ *                  
+ * Input          : scale_width = 0 1:1
+ *                                    = 1 1:2   
+ *                                    = 2 1:4   
+ *                  scale_height= 0 1:1
+ *                                    = 1 1:2
+ *                                    = 2 1:4
+ *                              
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_w_h_downsize(int scale_width, int scale_height)
+{
+    int scale;
+    unsigned char   tx_vcbuffer[5];
+
+    if (scale_width>=2) scale_width=2;
+    if (scale_height>scale_width)   scale_height=scale_width;
+    scale=(unsigned char)(scale_height<<2 | scale_width);
+
+
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_DOWNSIZE_SIZE;
+    tx_vcbuffer[3]=0x01;
+
+    tx_vcbuffer[4]=scale;       //bit[1:0] width zooming proportion
+                                //bit[3:2] height zooming proportion
+
+    buffer_send(tx_vcbuffer, 5);
+}
+
+/*******************************************************************************
+ * Function Name  : VC0706_read_frame_buffer
+ * Description    : read image data from FBUF 
+ *                  
+ * Input          : buffer_address(4 bytes); buffer_length(4 bytes)
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_read_frame_buffer(unsigned long buffer_address, unsigned long buffer_length)
+{
+    unsigned char   tx_vcbuffer[16];
+
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_READ_FBUF;
+    tx_vcbuffer[3]=0x0c;
+    tx_vcbuffer[4]=FBUF_CURRENT_FRAME;
+    tx_vcbuffer[5]=0x0a;        // 0x0a=data transfer by MCU mode; 0x0f=data transfer by SPI interface
+    tx_vcbuffer[6]=buffer_address>>24;          //starting address
+    tx_vcbuffer[7]=buffer_address>>16;          
+    tx_vcbuffer[8]=buffer_address>>8;           
+    tx_vcbuffer[9]=buffer_address&0x0ff;            
+    
+    tx_vcbuffer[10]=buffer_length>>24;      // data length
+    tx_vcbuffer[11]=buffer_length>>16;
+    tx_vcbuffer[12]=buffer_length>>8;       
+    tx_vcbuffer[13]=buffer_length&0x0ff;
+    tx_vcbuffer[14]=0x00;       // delay time
+    tx_vcbuffer[15]=0x0a;
+    
+
+    buffer_send(tx_vcbuffer, 16);
+}
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_get_frame_buffer_length
+ * Description    : Get frame buffer length
+ *                  
+ * Input          : None
+ * Output         : Frame Length
+ * Return         : None
+ *******************************************************************************/
+uint32_t CameraShield::VC0706_get_frame_buffer_length()
+{
+    unsigned char   tx_vcbuffer[20];
+    uint32_t    frame_length;        
+        
+    _serial.rxBufferFlush();
+    
+    //get frame buffer length
+    VC0706_get_framebuffer_length(0);
+    wait_ms(10);
+    buffer_read(tx_vcbuffer, sizeof(tx_vcbuffer));
+    
+    // store frame buffer length for coming reading
+    frame_length = (tx_vcbuffer[5]<<8) + tx_vcbuffer[6];
+    frame_length = frame_length << 16;
+    frame_length = frame_length + (0x0ff00 & (tx_vcbuffer[7]<<8)) + tx_vcbuffer[8];
+    
+    return frame_length;
+}
+
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_frame_control
+ * Description    : control frame buffer register
+ *                  
+ * Input          : frame_control=control flag(1byte)
+ *          :       0 = stop current frame ; 1= stop next frame;2=step frame;3 =resume frame;
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_frame_control(char frame_control)
+{
+    unsigned char   tx_vcbuffer[5];
+    
+    if(frame_control>3)frame_control=3;
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_FBUF_CTRL;
+    tx_vcbuffer[3]=0x01;
+    tx_vcbuffer[4]=frame_control;
+
+    buffer_send(tx_vcbuffer, 5);
+}
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_motion_detection
+ * Description    : get motion monitoring status in communication interface.
+ *                  
+ * Input          : control_flag = 0 stop motion monitoring
+ *                        = 1 start motion monitoring                  
+ *
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_motion_detection(int control_flag)
+{
+    unsigned char   tx_vcbuffer[5];
+    
+    
+    if(control_flag>1)control_flag=1;
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_COMM_MOTION_CTRL;
+    tx_vcbuffer[3]=0x01;
+    tx_vcbuffer[4]=control_flag;
+
+    buffer_send(tx_vcbuffer, 5);
+}
+
+/*******************************************************************************
+ * Function Name  : VC0706_motion_control
+ * Description    : motion control
+ *                  
+ * Input          : control_flag = 0 forbid motion monitoring
+ *                        = 1 enable motion monitoring                  
+ *
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_motion_control(int control_flag)
+{
+    unsigned char   tx_vcbuffer[7];
+    
+    
+    if(control_flag>1)control_flag=1;
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_MOTION_CTRL;
+    tx_vcbuffer[3]=0x03;
+    tx_vcbuffer[4]=0x00;            //motion control attribute
+    tx_vcbuffer[5]=0x01;            //mcu uart control
+    tx_vcbuffer[6]=control_flag;    
+
+    buffer_send(tx_vcbuffer, 7);
+}
+
+
+
+
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_get_framebuffer_length
+ * Description    : get byte-lengths in FBUF
+ *                  
+ * Input          : fbuf_type =current or next frame
+ *                      0   =  current frame
+ *                   1   =  next frame
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_get_framebuffer_length(char fbuf_type)
+{
+    unsigned char   tx_vcbuffer[5];
+    
+    if(fbuf_type>1)fbuf_type=1;
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_GET_FBUF_LEN;
+    tx_vcbuffer[3]=0x01;
+    tx_vcbuffer[4]=fbuf_type;
+
+    buffer_send(tx_vcbuffer, 5);
+}
+
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_uart_power_save
+ * Description    : stop current frame for reading
+ *                  
+ * Input          : power_on =1  start power-save
+ *                     = 0  stop power-save
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_uart_power_save(char power_save_on)
+{
+    unsigned char   tx_vcbuffer[7];
+    
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_POWER_SAVE_CTRL;
+    tx_vcbuffer[3]=0x03;
+    tx_vcbuffer[4]=00;          //power save control mode
+    tx_vcbuffer[5]=01;          // control by UART
+    tx_vcbuffer[6]=power_save_on;           //start power save
+    
+
+    buffer_send(tx_vcbuffer, 7);
+}
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_uart_color_control
+ * Description    : stop current frame for reading
+ *                  
+ * Input          : show_mode = 0  automatically step black-white and colour
+ *                         1  manually step color, select colour
+ *                         2    manually step color, select black-white
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_uart_color_control(char show_mode)
+{
+    unsigned char   tx_vcbuffer[6];
+    
+    if(show_mode>2) show_mode=2;
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_COLOR_CTRL;
+    tx_vcbuffer[3]=0x02;
+    tx_vcbuffer[4]=01;      //control by UART
+    tx_vcbuffer[5]=show_mode;       // automatically step black-white and colour
+
+    buffer_send(tx_vcbuffer, 6);
+}
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_image_size
+ * Description    : resizing the image
+ *                  
+ * Input          : VC0706_640x480
+ *                  VC0706_320x240
+ *                  VC0706_160x120
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_image_size(int ratio)
+{
+    unsigned char   tx_vcbuffer[9];
+    
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_WRITE_DATA;
+    tx_vcbuffer[3]=0x05;
+    tx_vcbuffer[4]=0x04;        
+    tx_vcbuffer[5]=0x01;        
+    tx_vcbuffer[6]=0x00;        
+    tx_vcbuffer[7]=0x19;
+    tx_vcbuffer[8]=ratio; //data
+
+    buffer_send(tx_vcbuffer, 9);
+}
+
+
+
+/*******************************************************************************
+ * Function Name  : VC0706_compression_ratio
+ * Description    : stop current frame for reading
+ *                  
+ * Input          : ration      >13(minimum)
+ *                      <63(max)
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_compression_ratio(int ratio)
+{
+    unsigned char   tx_vcbuffer[9];
+    
+    if(ratio>63)ratio=63;
+    if(ratio<13)ratio=13;
+    int vc_comp_ratio=(ratio-13)*4+53;
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_WRITE_DATA;
+    tx_vcbuffer[3]=0x05;
+    tx_vcbuffer[4]=01;      //chip register
+    tx_vcbuffer[5]=0x01;    //data num ready to write
+    tx_vcbuffer[6]=0x12;    //register address
+    tx_vcbuffer[7]=0x04;
+    tx_vcbuffer[8]=vc_comp_ratio; //data
+
+    buffer_send(tx_vcbuffer, 9);
+}
+    
+
+/*******************************************************************************
+ * Function Name  : VC0706_motion_windows_setting
+ * Description    : motion windows setting
+ *                  
+ * Input          : register_address(2 bytes); 
+ *              data(4 bytes)= data ready to write
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::VC0706_motion_windows_setting(unsigned int register_address, unsigned long data)
+{
+    unsigned char   tx_vcbuffer[12];
+    
+    tx_vcbuffer[0]=VC0706_PROTOCOL_SIGN;
+    tx_vcbuffer[1]=VC0706_SERIAL_NUMBER;
+    tx_vcbuffer[2]=VC0706_COMMAND_WRITE_DATA;
+    tx_vcbuffer[3]=0x08;
+    tx_vcbuffer[4]=01;      //chip register
+    tx_vcbuffer[5]=0x04;    //data num ready to write
+    tx_vcbuffer[6]=register_address>>8; //register address
+    tx_vcbuffer[7]=register_address&0x0ff;;
+
+    tx_vcbuffer[8]=data>>24;        // data ready to write
+    tx_vcbuffer[9]=data>>16;
+    tx_vcbuffer[10]=data>>8;        
+    tx_vcbuffer[11]=data&0x0ff;
+    
+    buffer_send(tx_vcbuffer, 12);
+}
+    
+
+
+/*******************************************************************************
+ * Function Name  : buffer_send
+ * Description    : Transmit buffer to VC0706
+ *                  
+ * Input          : buff pointer
+ *                : buffer length
+ *                  
+ * Output         : None
+ * Return         : None
+ *******************************************************************************/
+void CameraShield::buffer_send(unsigned char *buff, int buffSize)
+{
+    int i=0;
+
+    for (i=0;i<buffSize;i++)
+        _serial.putc(buff[i]);
+    
+    // Wait for buffer to send
+    while(_serial.txIsBusy())
+    {
+        wait_us(1);
+    }
+}
+
+
+
+/*******************************************************************************
+ * Function Name  : buffer_read
+ * Description    : Receive buffer from VC0706
+ *                  
+ * Input          : buffer pointer
+ *                : buffer size
+ *                  
+ * Output         : length of buffer read
+ * Return         : None
+ *******************************************************************************/
+int CameraShield::buffer_read(unsigned char *buff, int buffSize)
+{
+    bool validity=true;
+    int rx_counter = 0;
+    
+    buff[0]=0;
+    while (_serial.readable() > 0 && rx_counter < buffSize) 
+    {
+        buff[rx_counter++]= _serial.getc();
+    }
+
+    if (buff[0]!=0x76)
+        validity=false;
+    if (buff[1]!=VC0706_SERIAL_NUMBER)
+        validity=false;
+
+    if (validity)
+        return 0;
+        
+    return rx_counter;
+}
\ No newline at end of file