C328R camera save JPEGs to VDIP1 USB Thumbdrive

I was able to create a sketch which saves JPEGs created by a Comedia C328R camera to a USB thumbdrive plugged into a VDIP1 (Vinculum VNC1L Prototyping) Module.

A tweaked version of a C328R library using NewSoftSerial can be found at:
http://arms22.googlecode.com/files/CameraC328R.zip

The VDIP1 module is also using the NewSoftSerial library. My sketch handles the CTS and RTS handshaking for the VDIP1.
It starts communicating with the VDIP1 at 9600 baud and switches to 57600 on-the-fly. It still takes a while to save 640x480 image.

Each snapshot increments the file name - e.g. 1.jpg, 2.jpg …

NOTE: Resetting the Arduino instead of removing/restoring power will cause problems with changing the baud rate.
This could be addressed in various ways. The Vinculum Customiser software can change the default baud rate and other parameters.

#include <CameraC328R.h>
#include <NewSoftSerial.h>
#define LED_PIN 13

#define USB_BAUD 9600
#define CAMERA_BAUD 14400
#define VDIP_BAUD 9600
#define VDIP_19200 "$9C8000"
#define VDIP_38400 "$4EC000"
#define VDIP_57600 "$34C000"
#define VDIP_115200 "$1A0000"
#define purge false
#define show true

static uint16_t pictureSizeCount = 0;

int retval;

int picnum=1;                    // JPEG file counter
char fname[13];                // hold JPEG filename
char exten[5] = ".jpg";
char fnum[6];                    // ascii value of file counter

NewSoftSerial CamSer(8, 9);
NewSoftSerial VDIP1(2, 3);    
int RTSPin = 4;                // VDIP1 RTS
int CTSPin = 5;                //VDIP1 CTS

CameraC328R camera(&CamSer);            //instantiate camera object

void setup()
{
  pinMode( LED_PIN, OUTPUT );
  digitalWrite( LED_PIN, LOW );

  delay(2000);                                 //allow time for VDIP to settle
  pinMode(RTSPin, INPUT);
  pinMode(CTSPin, OUTPUT);
  delay(2000);                                 

  Serial.begin( USB_BAUD );
  CamSer.begin(CAMERA_BAUD);

  VDIP1.begin(VDIP_BAUD);
  //VDIP1.begin(57600);              // You can modify the default speed of the VDIP1 with firmware updates to be up to 57600 through newSoftSerial.
  digitalWrite(CTSPin, LOW);      // Set the VDIP CTS to low and keep it there.

  VDIP1.print("IPA");                    // Set to VDIP1 to ascii mode.
  VDIP1.print(13, BYTE);
  Response(show);
  delay(500);

//>>>>>>>>>>>change VDIP Baud Rate <<<<<<<<<<<<<<<<<
  VDIP1.print("SBD ");
//  VDIP1.print(VDIP_38400);     
  VDIP1.print(VDIP_57600);     
  VDIP1.print(13, BYTE);
  delay(50);
//  VDIP1.begin(38400);
  VDIP1.begin(57600);

  NextFile();                              // build next  file name
  delay(500);  Serial.println("Press enter to take picture");
}

void loop()
{
  Response(show);
  if( Serial.available() )
  {
    while(Serial.read() != -1);
    Serial.print("Deleting ");
    Serial.println(fname);
    VDIP1.print("DLF ");
    VDIP1.print(fname); 
    VDIP1.print(13, BYTE);
    WaitForResponse(purge, 1000);

    Serial.print("Open for writing: ");
    Serial.println(fname);
    VDIP1.print("OPW ");
    VDIP1.print(fname); 
    VDIP1.print(13, BYTE);
    //Response(show);
    WaitForResponse(show, 1000);
    delay(250);
  
    digitalWrite( LED_PIN, HIGH );
    retval = TakePic();
    if (retval == 1)
    {
      Serial.print("After failed attempt, close ");
      Serial.println(fname);
      VDIP1.print("CLF ");
      VDIP1.print(fname); 
      VDIP1.print(13, BYTE);
      Response(show);
      Serial.println("Press enter to take picture");
    }  
  }
}

int TakePic()                               // instruct camera to take snapshot
{  
    if( !camera.sync() )
    {
      Serial.println( "Sync failed." );
      return 1;
    }
    if( !camera.initial( CameraC328R::CT_JPEG, CameraC328R::PR_160x120, CameraC328R::JR_640x480 ) )
    {
      Serial.println( "Initial failed." );
      return 1;
    }
    if( !camera.setPackageSize( 64 ) )
    {
      Serial.println( "Package size failed." );
      return 1;
    }
    if( !camera.setLightFrequency( CameraC328R::FT_50Hz ) )
    {
      Serial.println( "Light frequency failed." );
      return 1;
    }
    if( !camera.snapshot( CameraC328R::ST_COMPRESSED, 0 ) )
    {
      Serial.println( "Snapshot failed." );
      return 1;
    }
    pictureSizeCount = 0;
    if( !camera.getJPEGPicture( CameraC328R::PT_JPEG, PROCESS_DELAY, &getJPEGPicture_callback ) )
    {
      Serial.println( "Get JPEG failed." );
      return 1;
    }
    return 0;
  }

/*
 This callback is called EVERY time a JPEG data packet is received from camera
*/
void getJPEGPicture_callback( uint16_t pictureSize, uint16_t packageSize, uint16_t packageCount, byte* package )
{
  // packageSize is the size of the picture part of the package
  pictureSizeCount += packageSize;
 
  VDIP1.print("WRF ");  
  VDIP1.print(packageSize);         // number of bytes to write
  VDIP1.print(13, BYTE);
  Response(purge);
  for( uint16_t i = 0; i < packageSize; i++ )
 {
   VDIP1.print(package[i], BYTE);
 } 

 Response(purge);
 delay(250);

  if( pictureSizeCount == pictureSize )
  {
    Serial.print("Closing ");
    Serial.println(fname);
    VDIP1.print("CLF "); 
    VDIP1.print(fname);
    VDIP1.print(13, BYTE);
//    Response(show);
    WaitForResponse(show, 1000);
    Serial.print("File size: ");
    Serial.println(pictureSize);
    NextFile();
    Serial.println("Press enter to take picture");
//    camera.powerOff();
    digitalWrite( LED_PIN, HIGH );         // DONE!
  }
}

void WaitForResponse(boolean action, unsigned long timeout)
{
  char charRead;
  unsigned long start = millis();
  while (millis() - start <= timeout)
  {
    if (VDIP1.available() > 0)
    { 
      if (VDIP1.available() > 32) 
      {
        digitalWrite(CTSPin, HIGH);
      } else {
        digitalWrite(CTSPin, LOW);
      }
      charRead = VDIP1.read();
      if (action == true)
      {
        if (charRead == 0x0D) {
          Serial.println();
        } else {
          Serial.print(charRead);
        }
      }
      if (charRead == 0x0D)            // carriage return?
      {
        return;
      }  
    }  
  } 
  Serial.print("Timeout: ");
  Serial.println(millis() - start);
}

void Response(boolean action)              // print (or purge) response from VDIP1 
{
  char charRead;
  while (VDIP1.available() > 0)
  {
    // Disable the sending on the VDIP1 device if you have filled more than 50% of your buffer (64 bytes by default)
    if (VDIP1.available() > 32) {
      digitalWrite(CTSPin, HIGH);
    } else {
      digitalWrite(CTSPin, LOW);
    }
    charRead = VDIP1.read();
    if (action == true)
    {
      if (charRead == 0x0D) {
        Serial.println();
      } else {
        Serial.print(charRead);
      }
    }  
  }
}

void NextFile()                                    //create next JPEG file name
{
   itoa(picnum, fnum, 10);
   fname[0] = '\0';
   strcat(fname, fnum);
   strcat(fname, exten);
   picnum++;
}

That's sweet. Maybe you could post a demo to the exhibition?