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(); 
    }
}

CameraShield.cpp

Committer:
davidr99
Date:
2014-12-18
Revision:
0:e5fc19091502

File content as of revision 0:e5fc19091502:

/*****************************************************************************************
** 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;
}