Carrie CohlmiaWilliam Neal
Published

Modular Motion Sensing and Surveillance

Monitoring the door, the cradle, or the bird feeder easily with this modular system!

BeginnerFull instructions provided5 hours1,946
Modular Motion Sensing and Surveillance

Things used in this project

Hardware components

ArduCAM OV5642
×1
Photon
Particle Photon
×2
SparkFun PIR Motion Sensor
×1
Generic Wire Wrap
×1
5 mm LED: Red
5 mm LED: Red
×1
Solderless Breadboard Half Size
Solderless Breadboard Half Size
×2
Resistor 220 ohm
Resistor 220 ohm
×1

Software apps and online services

ThingSpeak API
ThingSpeak API
Particle Pi
Particle Pi

Story

Read more

Schematics

PIR Sensor Connection

ArduCam Connection

Code

cameraapp.ino

C/C++
// This #include statement was automatically added by the Particle IDE.
#include "ArduCAM.h"
#include "memorysaver.h""
#include "ArduCAM.h"
#include "ov5642_regs.h"
SYSTEM_THREAD(ENABLED);

#define VERSION_SLUG "7n"

TCPClient client;

#define SERVER_ADDRESS "your ip address here"
#define SERVER_TCP_PORT 5550

#define TX_BUFFER_MAX 1024
uint8_t buffer[TX_BUFFER_MAX + 1];
int tx_buffer_index = 0;
int imagesize = 0;
int count = 0;

const String key = "your key here"; //thingspeak write key

//#define SD_CS D2

// set pin A2 as the slave select for the ArduCAM shield
const int SPI_CS = A2;

// allow us to use itoa() in this scope
//extern char* itoa(int a, char* buffer, unsigned char radix);
//#define BMPIMAGEOFFSET 66
//const char bmp_header[BMPIMAGEOFFSET] PROGMEM =
//{
//      0x42, 0x4D, 0x36, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x28, 0x00,
//      0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x03, 0x00,
//      0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0x00, 0x00,
//      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x1F, 0x00,
//      0x00, 0x00
//};


ArduCAM myCAM(OV5642, SPI_CS);


void setup()
{
  Particle.publish("status", "Good morning, Version: " + String(VERSION_SLUG));
  delay(1000);

  uint8_t vid,pid;
  uint8_t temp;

  Wire.setSpeed(CLOCK_SPEED_100KHZ);
  Wire.begin();

  Serial.begin(115200);
  Serial.println("ArduCAM Start!");

  // set the SPI_CS as an output:
  pinMode(SPI_CS, OUTPUT);

  // initialize SPI:
  SPI.begin();
  //SPI.begin(SPI_MODE_MASTER);
  //SPI.begin(SPI_MODE_SLAVE, SPI_CS);


  while(1) {
    Particle.publish("status", "checking for camera");
    Serial.println("Checking for camera...");

    //Check if the ArduCAM SPI bus is OK
    myCAM.write_reg(ARDUCHIP_TEST1, 0x55);
    temp = myCAM.read_reg(ARDUCHIP_TEST1);
    if(temp != 0x55)
    {
      Particle.publish("stats", "SPI interface Error!");
      Serial.println("SPI interface Error!");
      Particle.publish("status", "myCam.read_reg said " + String(temp));
      Serial.println("myCam.read_reg said " + String(temp));
      delay(5000);
    }
    else {
      break;
    }
    Particle.process();
  }

    Particle.publish("status", "Camera found.");


while(1){
  //Check if the camera module type is OV5642
  myCAM.rdSensorReg16_8(OV5642_CHIPID_HIGH, &vid);
  myCAM.rdSensorReg16_8(OV5642_CHIPID_LOW, &pid);
  if ((vid != 0x56) || (pid != 0x42)){
    Serial.println(F("Can't find OV5642 module!"));
    Particle.publish("status", "Not found, camera says " + String::format("%d:%d", vid, pid));
    delay(5000);
    continue;
  }
  else {
    Serial.println(F("OV5642 detected."));
    Particle.publish("status", "OV5642 detected: " + String::format("%d:%d", vid, pid));
    break;
  }
}


  Serial.println("Camera found, initializing...");
    //myCAM.write_reg(ARDUCHIP_MODE, 0x01);		 	//Switch to CAM

    //Change MCU mode
    myCAM.set_format(JPEG);
    delay(100);

    myCAM.InitCAM();
    delay(100);

//    myCAM.set_format(JPEG);
//    delay(100);

    myCAM.set_bit(ARDUCHIP_TIM, VSYNC_LEVEL_MASK);
    //myCAM.write_reg(ARDUCHIP_TIM, VSYNC_LEVEL_MASK);
    delay(100);

    myCAM.clear_fifo_flag();
    delay(100);

    myCAM.write_reg(ARDUCHIP_FRAMES,0x00);
    delay(100);

    myCAM.OV5642_set_JPEG_size(OV5642_320x240);
    //myCAM.OV5640_set_JPEG_size(OV5642_1600x1200);
    //myCAM.OV5640_set_JPEG_size(OV5642_640x480);    // ?
    //delay(100);

    // wait a sec`
    delay(1000);


    client.connect(SERVER_ADDRESS, SERVER_TCP_PORT);

    Particle.subscribe("KN_motion", KN_motion);
}



void loop()
{
    if (!client.connected()) {
        //client.stop();
        Particle.publish("status", "Attempting to reconnect to TCP Server...");
        if (!client.connect(SERVER_ADDRESS, SERVER_TCP_PORT)) {
            delay(5000);
            return;
        }
    }
}
    
    
void KN_motion(const char *event, const char *data)    
{    
    Particle.publish("status_start", "1"); //Taking a picture...
    Serial.println("Taking a picture...");


    //myCAM.OV5640_set_JPEG_size(OV5640_320x240);   //works
    //myCAM.OV5640_set_JPEG_size(OV5642_1600x1200); //doesn't work
    //myCAM.OV5640_set_JPEG_size(OV5642_1280x960);  // doesn't work?
    //myCAM.OV5640_set_JPEG_size(OV5642_640x480);    // ?

    myCAM.OV5642_set_JPEG_size(OV5642_2592x1944); //works
    delay(100);

    //myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
    //myCAM.clear_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);


    myCAM.flush_fifo();
    delay(100);

    myCAM.clear_fifo_flag();
    delay(100);

    myCAM.start_capture();
    delay(100);



    //myCAM.start_capture();
    unsigned long start_time = millis(),
                  last_publish = millis();


//
//  wait for the photo to be done
//
    while(!myCAM.get_bit(ARDUCHIP_TRIG , CAP_DONE_MASK)) {
        Particle.process();
        delay(10);

        unsigned long now = millis();
        if ((now - last_publish) > 1000) {
            Particle.publish("status", "waiting for photo " + String(now-start_time));
            last_publish = now;
        }

        if ((now-start_time) > 30000) {
            Particle.publish("status", "bailing...");
            break;
        }
    }
    delay(100);

count++;
 Serial.print("Updating Thingspeak:");
    Serial.print(count);
    int length = myCAM.read_fifo_length();
    int imagesize = length;

    Serial.println("Image size is " + String(length));
    
    Particle.publish("imagesize", String(imagesize));
    Particle.publish("thingSpeakWrite_All", +
          "{ \"2\": \"" + String(imagesize) + "\"," +
          "\"k\": \"" + key + "\" }", 60, PRIVATE);

    delay(5000); 



    uint8_t temp = 0xff, temp_last = 0;
    int bytesRead = 0;



    if(myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK))
    {
        delay(100);
        Serial.println(F("ACK CMD CAM Capture Done."));
        Particle.publish("status", "Capture Done");

        //myCAM.CS_LOW();

        myCAM.set_fifo_burst();


        //#if !(defined (OV5642_MINI_5MP_PLUS) ||(defined (ARDUCAM_SHIELD_V2) && defined (OV5642_CAM)))
        //SPI.transfer(0xFF);
        //#endif

        tx_buffer_index = 0;
        temp = 0;

        //while (bytesRead < length)
        while( (temp != 0xD9) | (temp_last != 0xFF) )
        {
            temp_last = temp;
            temp = myCAM.read_fifo();
            bytesRead++;


            buffer[tx_buffer_index++] = temp;

            if (tx_buffer_index >= TX_BUFFER_MAX) {
                client.write(buffer, tx_buffer_index);

                tx_buffer_index = 0;
                Particle.process();
            }

            if (bytesRead > 2048000) {
                // failsafe
                break;
            }
        }


        if (tx_buffer_index != 0) {
            client.write(buffer, tx_buffer_index);
        }

        //Clear the capture done flag
        //myCAM.CS_HIGH();
        myCAM.clear_fifo_flag();

        Serial.println(F("End of Photo"));
    }

    //Serial.println("sleeping 10 seconds");
    //Particle.publish("status", "Sleeping 10 seconds");
    //delay(10 * 1000);
}

ov5642_regs.h

C/C++
#ifndef OV5642_REGS_H
#define OV5642_REGS_H
#include "ArduCAM.h"
//#include <avr/pgmspace.h>

#define OV5642_CHIPID_HIGH 0x300a
#define OV5642_CHIPID_LOW 0x300b

const struct sensor_reg ov5642_320x240[] PROGMEM =
{
	{0x3800 ,0x1 },
	{0x3801 ,0xa8},
	{0x3802 ,0x0 },
	{0x3803 ,0xA },
	{0x3804 ,0xA },
	{0x3805 ,0x20},
	{0x3806 ,0x7 },
	{0x3807 ,0x98},
	{0x3808 ,0x1 },
	{0x3809 ,0x40},
	{0x380a ,0x0 },
	{0x380b ,0xF0},
	{0x380c ,0xc },
	{0x380d ,0x80},
	{0x380e ,0x7 },
	{0x380f ,0xd0},
	{0x5001 ,0x7f},
	{0x5680 ,0x0 },
	{0x5681 ,0x0 },
	{0x5682 ,0xA },
	{0x5683 ,0x20},
	{0x5684 ,0x0 },
	{0x5685 ,0x0 },
	{0x5686 ,0x7 },
	{0x5687 ,0x98},
	{0x3801, 0xb0},
	{0xffff, 0xff},
};

const struct sensor_reg ov5642_640x480[] PROGMEM =
{
	{0x3800 ,0x1 },
	{0x3801 ,0xa8},
	{0x3802 ,0x0 },
	{0x3803 ,0xA },
	{0x3804 ,0xA },
	{0x3805 ,0x20},
	{0x3806 ,0x7 },
	{0x3807 ,0x98},
	{0x3808 ,0x2 },
	{0x3809 ,0x80},
	{0x380a ,0x1 },
	{0x380b ,0xe0},
	{0x380c ,0xc },
	{0x380d ,0x80},
	{0x380e ,0x7 },
	{0x380f ,0xd0},
	{0x5001 ,0x7f},
	{0x5680 ,0x0 },
	{0x5681 ,0x0 },
	{0x5682 ,0xA },
	{0x5683 ,0x20},
	{0x5684 ,0x0 },
	{0x5685 ,0x0 },
	{0x5686 ,0x7 },
	{0x5687 ,0x98},
	{0x3801, 0xb0},
	{0xffff, 0xff},
};

const struct sensor_reg ov5642_1280x960[] PROGMEM =
{
	{0x3800 ,0x1 },
	{0x3801 ,0xB0},
	{0x3802 ,0x0 },
	{0x3803 ,0xA },
	{0x3804 ,0xA },
	{0x3805 ,0x20},
	{0x3806 ,0x7 },
	{0x3807 ,0x98},
	{0x3808 ,0x5 },
	{0x3809 ,0x00},
	{0x380a ,0x3 },
	{0x380b ,0xC0},
	{0x380c ,0xc },
	{0x380d ,0x80},
	{0x380e ,0x7 },
	{0x380f ,0xd0},
	{0x5001 ,0x7f},
	{0x5680 ,0x0 },
	{0x5681 ,0x0 },
	{0x5682 ,0xA },
	{0x5683 ,0x20},
	{0x5684 ,0x0 },
	{0x5685 ,0x0 },
	{0x5686 ,0x7 },
	{0x5687 ,0x98},
	{0xffff, 0xff},
};

const struct sensor_reg ov5642_1600x1200[] PROGMEM =
{
	{0x3800 ,0x1 },
	{0x3801 ,0xB0},
	{0x3802 ,0x0 },
	{0x3803 ,0xA },
	{0x3804 ,0xA },
	{0x3805 ,0x20},
	{0x3806 ,0x7 },
	{0x3807 ,0x98},
	{0x3808 ,0x6 },
	{0x3809 ,0x40},
	{0x380a ,0x4 },
	{0x380b ,0xB0},
	{0x380c ,0xc },
	{0x380d ,0x80},
	{0x380e ,0x7 },
	{0x380f ,0xd0},
	{0x5001 ,0x7f},
	{0x5680 ,0x0 },
	{0x5681 ,0x0 },
	{0x5682 ,0xA },
	{0x5683 ,0x20},
	{0x5684 ,0x0 },
	{0x5685 ,0x0 },
	{0x5686 ,0x7 },
	{0x5687 ,0x98},
	{0xffff, 0xff},
};

const struct sensor_reg ov5642_1024x768[] PROGMEM =
{
	{0x3800 ,0x1 },
	{0x3801 ,0xB0},
	{0x3802 ,0x0 },
	{0x3803 ,0xA },
	{0x3804 ,0xA },
	{0x3805 ,0x20},
	{0x3806 ,0x7 },
	{0x3807 ,0x98},
	{0x3808 ,0x4 },
	{0x3809 ,0x0},
	{0x380a ,0x3 },
	{0x380b ,0x0},
	{0x380c ,0xc },
	{0x380d ,0x80},
	{0x380e ,0x7 },
	{0x380f ,0xd0},
	{0x5001 ,0x7f},
	{0x5680 ,0x0 },
	{0x5681 ,0x0 },
	{0x5682 ,0xA },
	{0x5683 ,0x20},
	{0x5684 ,0x0 },
	{0x5685 ,0x0 },
	{0x5686 ,0x7 },
	{0x5687 ,0x98},
	{0xffff, 0xff},
};

const struct sensor_reg ov5642_2048x1536[] PROGMEM =
{
	{0x3800 ,0x01},
	{0x3801 ,0xb0},
	{0x3802 ,0x00},
	{0x3803 ,0x0a},
	{0x3804 ,0x0a},
	{0x3805 ,0x20},
	{0x3806 ,0x07},
	{0x3807 ,0x98},

	{0x3808 ,0x08},
	{0x3809 ,0x00},
	{0x380a ,0x06},
	{0x380b ,0x00},

	{0x380c ,0x0c},
	{0x380d ,0x80},
	{0x380e ,0x07},
	{0x380f ,0xd0},
	{0x3810 ,0xc2},
	{0x3815 ,0x44},
	{0x3818 ,0xa8},
	{0x3824 ,0x01},
	{0x3827 ,0x0a},
	{0x3a00 ,0x78},
	{0x3a0d ,0x10},
	{0x3a0e ,0x0d},
	{0x3a00 ,0x78},
	{0x460b ,0x35},
	{0x471d ,0x00},
	{0x471c ,0x50},
	{0x5682 ,0x0a},
	{0x5683 ,0x20},
	{0x5686 ,0x07},
	{0x5687 ,0x98},
	{0x589b ,0x00},
	{0x589a ,0xc0},
	//{0x4407 ,0x08},
	{0x589b ,0x00},
	{0x589a ,0xc0},
	{0x3002 ,0x0c},
	{0x3002 ,0x00},
	{0x4300 ,0x32},
	{0x460b ,0x35},
	{0x3002 ,0x0c},
	{0x3002 ,0x00},
	{0x4713 ,0x02},
	{0x4600 ,0x80},
	{0x4721 ,0x02},
	{0x471c ,0x40},
	{0x4408 ,0x00},
	{0x460c ,0x22},
	{0x3815 ,0x04},
	{0x3818 ,0xc8},
	{0x501f ,0x00},
	{0x5002 ,0xe0},
	{0x440a ,0x01},
	{0x4402 ,0x90},
	{0x3811 ,0xf0},	
	{0x3818, 0xa8},
	{0x3621, 0x10},	
	{0xffff, 0xff},
};

const struct sensor_reg ov5642_2592x1944[] PROGMEM =
{
	{0x3800 ,0x1 },
	{0x3801 ,0xB0},
	{0x3802 ,0x0 },
	{0x3803 ,0xA },
	{0x3804 ,0xA },
	{0x3805 ,0x20},
	{0x3806 ,0x7 },
	{0x3807 ,0x98},
	{0x3808 ,0xA },
	{0x3809 ,0x20},
	{0x380a ,0x7 },
	{0x380b ,0x98},
	{0x380c ,0xc },
	{0x380d ,0x80},
	{0x380e ,0x7 },
	{0x380f ,0xd0},
	{0x5001 ,0x7f},
	{0x5680 ,0x0 },
	{0x5681 ,0x0 },
	{0x5682 ,0xA },
	{0x5683 ,0x20},
	{0x5684 ,0x0 },
	{0x5685 ,0x0 },
	{0x5686 ,0x7 },
	{0x5687 ,0x98},
	{0xffff, 0xff},
};

const struct sensor_reg ov5642_dvp_zoom8[] PROGMEM=
{

	{0x3800 ,0x5 },
	{0x3801 ,0xf8},
	{0x3802 ,0x3 },
	{0x3803 ,0x5c},
	{0x3804 ,0x1 },
	{0x3805 ,0x44},
	{0x3806 ,0x0 },
	{0x3807 ,0xf0},
	{0x3808 ,0x1 },
	{0x3809 ,0x40},
	{0x380a ,0x0 },
	{0x380b ,0xf0},
	{0x380c ,0xc },
	{0x380d ,0x80},
	{0x380e ,0x7 },
	{0x380f ,0xd0},
	
	{0x5001 ,0x7f},
	{0x5680 ,0x0 },
	{0x5681 ,0x0 },
	{0x5682 ,0x1 },
	{0x5683 ,0x44},
	{0x5684 ,0x0 },
	{0x5685 ,0x0 },
	{0x5686 ,0x0 },
	{0x5687 ,0xf3},
	/*
	{0x381c ,0x21},
	{0x3524 ,0x0 },
	{0x3825 ,0x0 },
	{0x3826 ,0x0 },
	{0x3827 ,0x0 },
	{0x3010 ,0x70},
*/

	{0xffff, 0xff},
};

const struct sensor_reg OV5642_QVGA_Preview[] PROGMEM =
{
	{0x3103 ,0x93},
	{0x3008 ,0x82},
	{0x3017 ,0x7f},
	{0x3018 ,0xfc},
	{0x3810 ,0xc2},
	{0x3615 ,0xf0},
	{0x3000 ,0x00},
	{0x3001 ,0x00},
	{0x3002 ,0x5c},
	{0x3003 ,0x00},
	{0x3004 ,0xff},
	{0x3005 ,0xff},
	{0x3006 ,0x43},
	{0x3007 ,0x37},
	{0x3011 ,0x08},
	{0x3010 ,0x10},
	{0x460c ,0x22},
	{0x3815 ,0x04},
	{0x370c ,0xa0},
	{0x3602 ,0xfc},
	{0x3612 ,0xff},
	{0x3634 ,0xc0},
	{0x3613 ,0x00},
	{0x3605 ,0x7c},
	{0x3621 ,0x09},
	{0x3622 ,0x60},
	{0x3604 ,0x40},
	{0x3603 ,0xa7},
	{0x3603 ,0x27},
	{0x4000 ,0x21},
	{0x401d ,0x22},
	{0x3600 ,0x54},
	{0x3605 ,0x04},
	{0x3606 ,0x3f},
	{0x3c01 ,0x80},
	{0x5000 ,0x4f},
	{0x5020 ,0x04},
	{0x5181 ,0x79},
	{0x5182 ,0x00},
	{0x5185 ,0x22},
	{0x5197 ,0x01},
	{0x5001 ,0xff},
	{0x5500 ,0x0a},
	{0x5504 ,0x00},
	{0x5505 ,0x7f},
	{0x5080 ,0x08},
	{0x300e ,0x18},
	{0x4610 ,0x00},
	{0x471d ,0x05},
	{0x4708 ,0x06},
	{0x3808 ,0x02},
	{0x3809 ,0x80},
	{0x380a ,0x01},
	{0x380b ,0xe0},
	{0x380e ,0x07},
	{0x380f ,0xd0},
	{0x501f ,0x00},
	{0x5000 ,0x4f},
	{0x4300 ,0x30},
	{0x3503 ,0x07},
	{0x3501 ,0x73},
	{0x3502 ,0x80},
	{0x350b ,0x00},
	{0x3503 ,0x07},
	{0x3824 ,0x11},
	{0x3501 ,0x1e},
	{0x3502 ,0x80},
	{0x350b ,0x7f},
	{0x380c ,0x0c},
	{0x380d ,0x80},
	{0x380e ,0x03},
	{0x380f ,0xe8},
	{0x3a0d ,0x04},
	{0x3a0e ,0x03},
	{0x3818 ,0xc1},
	{0x3705 ,0xdb},
	{0x370a ,0x81},
	{0x3801 ,0x80},
	{0x3621 ,0x87},
	{0x3801 ,0x50},
	{0x3803 ,0x08},
	{0x3827 ,0x08},
	{0x3810 ,0x40},
	{0x3804 ,0x05},
	{0x3805 ,0x00},
	{0x5682 ,0x05},
	{0x5683 ,0x00},
	{0x3806 ,0x03},
	{0x3807 ,0xc0},
	{0x5686 ,0x03},
	{0x5687 ,0xbc},
	{0x3a00 ,0x78},
	{0x3a1a ,0x05},
	{0x3a13 ,0x30},
	{0x3a18 ,0x00},
	{0x3a19 ,0x7c},
	{0x3a08 ,0x12},
	{0x3a09 ,0xc0},
	{0x3a0a ,0x0f},
	{0x3a0b ,0xa0},
	{0x350c ,0x07},
	{0x350d ,0xd0},
	{0x3500 ,0x00},
	{0x3501 ,0x00},
	{0x3502 ,0x00},
	{0x350a ,0x00},
	{0x350b ,0x00},
	{0x3503 ,0x00},
	{0x528a ,0x02},
	{0x528b ,0x04},
	{0x528c ,0x08},
	{0x528d ,0x08},
	{0x528e ,0x08},
	{0x528f ,0x10},
	{0x5290 ,0x10},
	{0x5292 ,0x00},
	{0x5293 ,0x02},
	{0x5294 ,0x00},
	{0x5295 ,0x02},
	{0x5296 ,0x00},
	{0x5297 ,0x02},
	{0x5298 ,0x00},
	{0x5299 ,0x02},
	{0x529a ,0x00},
	{0x529b ,0x02},
	{0x529c ,0x00},
	{0x529d ,0x02},
	{0x529e ,0x00},
	{0x529f ,0x02},
	{0x3030 ,0x0b},
	{0x3a02 ,0x00},
	{0x3a03 ,0x7d},
	{0x3a04 ,0x00},
	{0x3a14 ,0x00},
	{0x3a15 ,0x7d},
	{0x3a16 ,0x00},
	{0x3a00 ,0x78},
	{0x3a08 ,0x09},
	{0x3a09 ,0x60},
	{0x3a0a ,0x07},
	{0x3a0b ,0xd0},
	{0x3a0d ,0x08},
	{0x3a0e ,0x06},
	{0x5193 ,0x70},
	{0x589b ,0x04},
	{0x589a ,0xc5},
	{0x401e ,0x20},
	{0x4001 ,0x42},
	{0x401c ,0x04},
	{0x528a ,0x01},
	{0x528b ,0x04},
	{0x528c ,0x08},
	{0x528d ,0x10},
	{0x528e ,0x20},
	{0x528f ,0x28},
	{0x5290 ,0x30},
	{0x5292 ,0x00},
	{0x5293 ,0x01},
	{0x5294 ,0x00},
	{0x5295 ,0x04},
	{0x5296 ,0x00},
	{0x5297 ,0x08},
	{0x5298 ,0x00},
	{0x5299 ,0x10},
	{0x529a ,0x00},
	{0x529b ,0x20},
	{0x529c ,0x00},
	{0x529d ,0x28},
	{0x529e ,0x00},
	{0x529f ,0x30},
	{0x5282 ,0x00},
	{0x5300 ,0x00},
	{0x5301 ,0x20},
	{0x5302 ,0x00},
	{0x5303 ,0x7c},
	{0x530c ,0x00},
	{0x530d ,0x0c},
	{0x530e ,0x20},
	{0x530f ,0x80},
	{0x5310 ,0x20},
	{0x5311 ,0x80},
	{0x5308 ,0x20},
	{0x5309 ,0x40},
	{0x5304 ,0x00},
	{0x5305 ,0x30},
	{0x5306 ,0x00},
	{0x5307 ,0x80},
	{0x5314 ,0x08},
	{0x5315 ,0x20},
	{0x5319 ,0x30},
	{0x5316 ,0x10},
	{0x5317 ,0x00},
	{0x5318 ,0x02},
	{0x5402 ,0x3f},
	{0x5403 ,0x00},
	{0x3406 ,0x00},
	{0x5180 ,0xff},
	{0x5181 ,0x52},
	{0x5182 ,0x11},
	{0x5183 ,0x14},
	{0x5184 ,0x25},
	{0x5185 ,0x24},
	{0x5186 ,0x06},
	{0x5187 ,0x08},
	{0x5188 ,0x08},
	{0x5189 ,0x7c},
	{0x518a ,0x60},
	{0x518b ,0xb2},
	{0x518c ,0xb2},
	{0x518d ,0x44},
	{0x518e ,0x3d},
	{0x518f ,0x58},
	{0x5190 ,0x46},
	{0x5191 ,0xf8},
	{0x5192 ,0x04},
	{0x5193 ,0x70},
	{0x5194 ,0xf0},
	{0x5195 ,0xf0},
	{0x5196 ,0x03},
	{0x5197 ,0x01},
	{0x5198 ,0x04},
	{0x5199 ,0x12},
	{0x519a ,0x04},
	{0x519b ,0x00},
	{0x519c ,0x06},
	{0x519d ,0x82},
	{0x519e ,0x00},
	{0x5025 ,0x80},
	{0x5583 ,0x40},
	{0x5584 ,0x40},
	{0x5580 ,0x02},
	{0x5000 ,0xcf},
	{0x3710 ,0x10},
	{0x3632 ,0x51},
	{0x3702 ,0x10},
	{0x3703 ,0xb2},
	{0x3704 ,0x18},
	{0x370b ,0x40},
	{0x370d ,0x03},
	{0x3631 ,0x01},
	{0x3632 ,0x52},
	{0x3606 ,0x24},
	{0x3620 ,0x96},
	{0x5785 ,0x07},
	{0x3a13 ,0x30},
	{0x3600 ,0x52},
	{0x3604 ,0x48},
	{0x3606 ,0x1b},
	{0x370d ,0x0b},
	{0x370f ,0xc0},
	{0x3709 ,0x01},
	{0x3823 ,0x00},
	{0x5007 ,0x00},
	{0x5009 ,0x00},
	{0x5011 ,0x00},
	{0x5013 ,0x00},
	{0x519e ,0x00},
	{0x5086 ,0x00},
	{0x5087 ,0x00},
	{0x5088 ,0x00},
	{0x5089 ,0x00},
	{0x302b ,0x00},
	{0x3808 ,0x01},
	{0x3809 ,0x40},
	{0x380a ,0x00},
	{0x380b ,0xf0},
	{0x3a00 ,0x78},
	{0x5001 ,0xFF},
	{0x5583 ,0x50},
	{0x5584 ,0x50},
	{0x5580 ,0x02},
	{0x3c01 ,0x80},
	{0x3c00 ,0x04},    
	         
	{0x5800 ,0x48},
	{0x5801 ,0x31},
	{0x5802 ,0x21},
	{0x5803 ,0x1b},
	{0x5804 ,0x1a},
	{0x5805 ,0x1e},
	{0x5806 ,0x29},
	{0x5807 ,0x38},
	{0x5808 ,0x26},
	{0x5809 ,0x17},
	{0x580a ,0x11},
	{0x580b ,0xe },
	{0x580c ,0xd },
	{0x580d ,0xe },
	{0x580e ,0x13},
	{0x580f ,0x1a},
	{0x5810 ,0x15},
	{0x5811 ,0xd },
	{0x5812 ,0x8 },
	{0x5813 ,0x5 },
	{0x5814 ,0x4 },
	{0x5815 ,0x5 },
	{0x5816 ,0x9 },
	{0x5817 ,0xd },
	{0x5818 ,0x11},
	{0x5819 ,0xa },
	{0x581a ,0x4 },
	{0x581b ,0x0 },
	{0x581c ,0x0 },
	{0x581d ,0x1 },
	{0x581e ,0x6 },
	{0x581f ,0x9 },
	{0x5820 ,0x12},
	{0x5821 ,0xb },
	{0x5822 ,0x4 },
	{0x5823 ,0x0 },
	{0x5824 ,0x0 },
	{0x5825 ,0x1 },
	{0x5826 ,0x6 },
	{0x5827 ,0xa },
	{0x5828 ,0x17},
	{0x5829 ,0xf },
	{0x582a ,0x9 },
	{0x582b ,0x6 },
	{0x582c ,0x5 },
	{0x582d ,0x6 },
	{0x582e ,0xa },
	{0x582f ,0xe },
	{0x5830 ,0x28},
	{0x5831 ,0x1a},
	{0x5832 ,0x11},
	{0x5833 ,0xe },
	{0x5834 ,0xe },
	{0x5835 ,0xf },
	{0x5836 ,0x15},
	{0x5837 ,0x1d},
	{0x5838 ,0x6e},
	{0x5839 ,0x39},
	{0x583a ,0x27},
	{0x583b ,0x1f},
	{0x583c ,0x1e},
	{0x583d ,0x23},
	{0x583e ,0x2f},
	{0x583f ,0x41},
	{0x5840 ,0xe },
	{0x5841 ,0xc },
	{0x5842 ,0xd },
	{0x5843 ,0xc },
	{0x5844 ,0xc },
	{0x5845 ,0xc },
	{0x5846 ,0xc },
	{0x5847 ,0xc },
	{0x5848 ,0xd },
	{0x5849 ,0xe },
	{0x584a ,0xe },
	{0x584b ,0xa },
	{0x584c ,0xe },
	{0x584d ,0xe },
	{0x584e ,0x10},
	{0x584f ,0x10},
	{0x5850 ,0x11},
	{0x5851 ,0xa },
	{0x5852 ,0xf },
	{0x5853 ,0xe },
	{0x5854 ,0x10},
	{0x5855 ,0x10},
	{0x5856 ,0x10},
	{0x5857 ,0xa },
	{0x5858 ,0xe },
	{0x5859 ,0xe },
	{0x585a ,0xf },
	{0x585b ,0xf },
	{0x585c ,0xf },
	{0x585d ,0xa },
	{0x585e ,0x9 },
	{0x585f ,0xd },
	{0x5860 ,0xc },
	{0x5861 ,0xb },
	{0x5862 ,0xd },
	{0x5863 ,0x7 },
	{0x5864 ,0x17},
	{0x5865 ,0x14},
	{0x5866 ,0x18},
	{0x5867 ,0x18},
	{0x5868 ,0x16},
	{0x5869 ,0x12},
	{0x586a ,0x1b},
	{0x586b ,0x1a},
	{0x586c ,0x16},
	{0x586d ,0x16},
	{0x586e ,0x18},
	{0x586f ,0x1f},
	{0x5870 ,0x1c},
	{0x5871 ,0x16},
	{0x5872 ,0x10},
	{0x5873 ,0xf },
	{0x5874 ,0x13},
	{0x5875 ,0x1c},
	{0x5876 ,0x1e},
	{0x5877 ,0x17},
	{0x5878 ,0x11},
	{0x5879 ,0x11},
	{0x587a ,0x14},
	{0x587b ,0x1e},
	{0x587c ,0x1c},
	{0x587d ,0x1c},
	{0x587e ,0x1a},
	{0x587f ,0x1a},
	{0x5880 ,0x1b},
	{0x5881 ,0x1f},
	{0x5882 ,0x14},
	{0x5883 ,0x1a},
	{0x5884 ,0x1d},
	{0x5885 ,0x1e},
	{0x5886 ,0x1a},
	{0x5887 ,0x1a},
	        
	{0x5180 ,0xff},
	{0x5181 ,0x52},
	{0x5182 ,0x11},
	{0x5183 ,0x14},
	{0x5184 ,0x25},
	{0x5185 ,0x24},
	{0x5186 ,0x14},
	{0x5187 ,0x14},
	{0x5188 ,0x14},
	{0x5189 ,0x69},
	{0x518a ,0x60},
	{0x518b ,0xa2},
	{0x518c ,0x9c},
	{0x518d ,0x36},
	{0x518e ,0x34},
	{0x518f ,0x54},
	{0x5190 ,0x4c},
	{0x5191 ,0xf8},
	{0x5192 ,0x04},
	{0x5193 ,0x70},
	{0x5194 ,0xf0},
	{0x5195 ,0xf0},
	{0x5196 ,0x03},
	{0x5197 ,0x01},
	{0x5198 ,0x05},
	{0x5199 ,0x2f},
	{0x519a ,0x04},
	{0x519b ,0x00},
	{0x519c ,0x06},
	{0x519d ,0xa0},
	{0x519e ,0xa0},
	          
	{0x528a ,0x00},
	{0x528b ,0x01},
	{0x528c ,0x04},
	{0x528d ,0x08},
	{0x528e ,0x10},
	{0x528f ,0x20},
	{0x5290 ,0x30},
	{0x5292 ,0x00},
	{0x5293 ,0x00},
	{0x5294 ,0x00},
	{0x5295 ,0x01},
	{0x5296 ,0x00},
	{0x5297 ,0x04},
	{0x5298 ,0x00},
	{0x5299 ,0x08},
	{0x529a ,0x00},
	{0x529b ,0x10},
	{0x529c ,0x00},
	{0x529d ,0x20},
	{0x529e ,0x00},
	{0x529f ,0x30},
	{0x5282 ,0x00},
	{0x5300 ,0x00},
	{0x5301 ,0x20},
	{0x5302 ,0x00},
	{0x5303 ,0x7c},
	{0x530c ,0x00},
	{0x530d ,0x10},
	{0x530e ,0x20},
	{0x530f ,0x80},
	{0x5310 ,0x20},
	{0x5311 ,0x80},
	{0x5308 ,0x20},
	{0x5309 ,0x40},
	{0x5304 ,0x00},
	{0x5305 ,0x30},
	{0x5306 ,0x00},
	{0x5307 ,0x80},
	{0x5314 ,0x08},
	{0x5315 ,0x20},
	{0x5319 ,0x30},
	{0x5316 ,0x10},
	{0x5317 ,0x00},
	{0x5318 ,0x02},
	          
	{0x5380 ,0x01},  
	{0x5381 ,0x00},  
	{0x5382 ,0x00},  
	{0x5383 ,0x1f},  
	{0x5384 ,0x00},  
	{0x5385 ,0x06},  
	{0x5386 ,0x00},  
	{0x5387 ,0x00},  
	{0x5388 ,0x00},  
	{0x5389 ,0xE1},  
	{0x538A ,0x00},  
	{0x538B ,0x2B},  
	{0x538C ,0x00},  
	{0x538D ,0x00},  
	{0x538E ,0x00},  
	{0x538F ,0x10},  
	{0x5390 ,0x00},  
	{0x5391 ,0xB3},  
	{0x5392 ,0x00},  
	{0x5393 ,0xA6},  
	{0x5394 ,0x08}, 
	        
	{0x5480 ,0x0c},  
	{0x5481 ,0x18},  
	{0x5482 ,0x2f},  
	{0x5483 ,0x55},  
	{0x5484 ,0x64},  
	{0x5485 ,0x71},  
	{0x5486 ,0x7d},  
	{0x5487 ,0x87},  
	{0x5488 ,0x91},  
	{0x5489 ,0x9a},  
	{0x548A ,0xaa},  
	{0x548B ,0xb8},  
	{0x548C ,0xcd},  
	{0x548D ,0xdd},  
	{0x548E ,0xea},  
	{0x548F ,0x1d},  
	{0x5490 ,0x05},  
	{0x5491 ,0x00},  
	{0x5492 ,0x04},  
	{0x5493 ,0x20},  
	{0x5494 ,0x03},  
	{0x5495 ,0x60},  
	{0x5496 ,0x02},  
	{0x5497 ,0xB8},  
	{0x5498 ,0x02},  
	{0x5499 ,0x86},  
	{0x549A ,0x02},  
	{0x549B ,0x5B},  
	{0x549C ,0x02},  
	{0x549D ,0x3B},  
	{0x549E ,0x02},  
	{0x549F ,0x1C},  
	{0x54A0 ,0x02},  
	{0x54A1 ,0x04},  
	{0x54A2 ,0x01},  
	{0x54A3 ,0xED},  
	{0x54A4 ,0x01},  
	{0x54A5 ,0xC5},  
	{0x54A6 ,0x01},  
	{0x54A7 ,0xA5},  
	{0x54A8 ,0x01},  
	{0x54A9 ,0x6C},  
	{0x54AA ,0x01},  
	{0x54AB ,0x41},  
	{0x54AC ,0x01},  
	{0x54AD ,0x20},  
	{0x54AE ,0x00},  
	{0x54AF ,0x16},  
	{0x54B0 ,0x01}, 
	{0x54B1 ,0x20}, 
	{0x54B2 ,0x00},
	{0x54B3 ,0x10}, 
	{0x54B4 ,0x00},
	{0x54B5 ,0xf0}, 
	{0x54B6 ,0x00},
	{0x54B7 ,0xDF}, 
	{0x5402 ,0x3f}, 
	{0x5403 ,0x00},
	   
	{0x5500 ,0x10},
	{0x5502 ,0x00},
	{0x5503 ,0x06},
	{0x5504 ,0x00},
	{0x5505 ,0x7f},
	           
	{0x5025 ,0x80},
	{0x3a0f ,0x30},
	{0x3a10 ,0x28},
	{0x3a1b ,0x30},
	{0x3a1e ,0x28},
	{0x3a11 ,0x61},
	{0x3a1f ,0x10},
	{0x5688 ,0xfd},
	{0x5689 ,0xdf},
	{0x568a ,0xfe},
	{0x568b ,0xef},
	{0x568c ,0xfe},
	{0x568d ,0xef},
	{0x568e ,0xaa},
	{0x568f ,0xaa},



	{0xffff,0xff},
};        

const struct sensor_reg OV5642_JPEG_Capture_QSXGA[] PROGMEM =
{
	// OV5642_ QSXGA _YUV7.5 fps
	// 24 MHz input clock, 24Mhz pclk
	// jpeg mode 7.5fps

	{0x3503 ,0x07},	//AEC Manual Mode Control
	{0x3000 ,0x00},	//SYSTEM RESET00
	{0x3001 ,0x00},	//Reset for Individual Block
	{0x3002 ,0x00},	//Reset for Individual Block
	{0x3003 ,0x00},	//Reset for Individual Block
	{0x3005 ,0xff},	//Clock Enable Control
	{0x3006 ,0xff},	//Clock Enable Control
	{0x3007 ,0x3f},	//Clock Enable Control
	{0x350c ,0x07},	//AEC VTS Output high bits
	{0x350d ,0xd0},	//AEC VTS Output low bits
	{0x3602 ,0xe4},	//Analog Control Registers
	{0x3612 ,0xac},	//Analog Control Registers
	{0x3613 ,0x44},	//Analog Control Registers
	{0x3621 ,0x27},	//Array Control 01
	{0x3622 ,0x08},	//Analog Control Registers
	{0x3623 ,0x22},	//Analog Control Registers
	{0x3604 ,0x60},	//Analog Control Registers	
	{0x3705 ,0xda},	//Analog Control Registers
	{0x370a ,0x80},	//Analog Control Registers
	{0x3801 ,0x8a},	//HS      
	{0x3803 ,0x0a},	//VS      
	{0x3804 ,0x0a},	//HW      
	{0x3805 ,0x20},	//HW      
	{0x3806 ,0x07},	//VH      
	{0x3807 ,0x98},	//VH      
	{0x3808 ,0x0a},	//DVPHO   
	{0x3809 ,0x20},	//DVPHO   
	{0x380a ,0x07},	//DVPVO   
	{0x380b ,0x98},	//DVPVO   
	{0x380c ,0x0c},	//HTS     
	{0x380d ,0x80},	//HTS     
	{0x380e ,0x07},	//VTS     
	{0x380f ,0xd0},	//VTS     
	{0x3810 ,0xc2},
	{0x3815 ,0x44},
	{0x3818 ,0xc8},	//Mirror NO, Compression enable
	{0x3824 ,0x01},	//RSV 
	{0x3827 ,0x0a},	//RSV
	{0x3a00 ,0x78},	//AEC System Control 0
	{0x3a0d ,0x10},	//60 Hz Max Bands in One Frame
	{0x3a0e ,0x0d},	//50 Hz Max Bands in One Frame
	{0x3a10 ,0x32},	//Stable Range Low Limit (enter)
	{0x3a1b ,0x3c},	//Stable Range High Limit (go out)
	{0x3a1e ,0x32},	//Stable Range Low Limit (go out)
	{0x3a11 ,0x80},	//Step Manual Mode, Fast Zone High Limit
	{0x3a1f ,0x20},	//Step Manual Mode, Fast Zone Low Limit
	{0x3a00 ,0x78},	//AEC System Control 0
	{0x460b ,0x35},	//RSV VFIFO Control 0B
	{0x471d ,0x00},	//DVP CONTROL 1D
	{0x4713 ,0x03},	//COMPRESSION MODE SELECT mode3
	{0x471c ,0x50},	//RSV
	{0x5682 ,0x0a},	//AVG X END
	{0x5683 ,0x20},	//AVG X END
	{0x5686 ,0x07},	//AVG Y END
	{0x5687 ,0x98},	//AVG Y END
	{0x5001 ,0x4f},	//ISP CONTROL 01, UV adjust/Line stretch/UV average/Color matrix/AWB enable
	{0x589b ,0x00}, //RSV
	{0x589a ,0xc0},	//RSV
	{0x4407 ,0x08},	//COMPRESSION CTRL07 Bit[5:0]: Quantization scale  0x02
	{0x589b ,0x00},	//RSV
	{0x589a ,0xc0},	//RSV
	{0x3002 ,0x0c},	//Reset for Individual Block, Reset SFIFO/compression
	{0x3002 ,0x00},	//Reset for Individual Block
	{0x3503 ,0x00},	//AEC Manual Mode Control, Auto enable
	//{0x3818, 0xa8},
	//{0x3621, 0x17},
	//{0x3801, 0xb0},
	{0x5025, 0x80},
	{0x3a0f, 0x48},
	{0x3a10, 0x40},
	{0x3a1b, 0x4a},
	{0x3a1e, 0x3e},
	{0x3a11, 0x70},
	{0x3a1f, 0x20},
	{0xffff, 0xff},

};


const struct sensor_reg OV5642_1080P_Video_setting[] PROGMEM = 
{
	{0x3103 ,0x93},
	{0x3008 ,0x82},
	{0x3017 ,0x7f},
	{0x3018 ,0xfc},
	{0x3810 ,0xc2},
	{0x3615 ,0xf0},
	{0x3000 ,0x00},
	{0x3001 ,0x00},
	{0x3002 ,0x00},
	{0x3003 ,0x00},
	{0x3004 ,0xff},
	{0x3030 ,0x0b},
	{0x3011 ,0x08},
	{0x3010 ,0x10},
	{0x3604 ,0x60},
	{0x3622 ,0x60},
	{0x3621 ,0x09},
	{0x3709 ,0x00},
	{0x4000 ,0x21},
...

This file has been truncated, please download it to see its full contents.

ArduCAM.cpp

C/C++
/*
  ArduCAM.cpp - Arduino library support for CMOS Image Sensor
  Copyright (C)2011-2015 ArduCAM.com. All right reserved

  Basic functionality of this library are based on the demo-code provided by
  ArduCAM.com. You can find the latest version of the library at
  http://www.ArduCAM.com

  Now supported controllers:
    - OV7670
    - MT9D111
    - OV7675
    - OV2640
    - OV3640
    - OV5642
    - OV7660
    - OV7725
    - MT9M112
    - MT9V111
    - OV5640
    - MT9M001
    - MT9T112
    - MT9D112

  We will add support for many other sensors in next release.

  Supported MCU platform
    - Theoretically support all Arduino families
      - Arduino UNO R3      (Tested)
      - Arduino MEGA2560 R3   (Tested)
      - Arduino Leonardo R3   (Tested)
      - Arduino Nano      (Tested)
      - Arduino DUE       (Tested)
      - Arduino Yun       (Tested)
      - Raspberry Pi      (Tested)
      - ESP8266-12        (Tested)

  If you make any modifications or improvements to the code, I would appreciate
  that you share the code with me so that I might include it in the next release.
  I can be contacted through http://www.ArduCAM.com

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/*------------------------------------
  Revision History:
  2012/09/20  V1.0.0  by Lee  first release
  2012/10/23  V1.0.1  by Lee  Resolved some timing issue for the Read/Write Register
  2012/11/29  V1.1.0  by Lee  Add support for MT9D111 sensor
  2012/12/13  V1.2.0  by Lee  Add support for OV7675 sensor
  2012/12/28  V1.3.0  by Lee  Add support for OV2640,OV3640,OV5642 sensors
  2013/02/26  V2.0.0  by Lee  New Rev.B shield hardware, add support for FIFO control
                              and support Mega1280/2560 boards
  2013/05/28  V2.1.0  by Lee  Add support all drawing functions derived from UTFT library
  2013/08/24  V3.0.0  by Lee  Support ArudCAM shield Rev.C hardware, features SPI interface and low power mode.
                Support almost all series of Arduino boards including DUE.
  2014/02/06  V3.0.1  by Lee  Minor change to the library, fixed some bugs, add self test code to the sketches for easy debugging.
  2014/03/09  V3.1.0  by Lee  Add the more impressive example sketches.
                Optimise the OV5642 settings, improve image quality.
                Add live preview before JPEG capture.
                Add play back photos one by one after BMP capture.
  2014/05/01  V3.1.1  by Lee  Minor changes to add support Arduino IDE for linux distributions.
  2014/09/30  V3.2.0  by Lee  Improvement on OV5642 camera dirver.
  2014/10/06  V3.3.0  by Lee  Add OV7660,OV7725 camera support.
  2015/02/27  V3.4.0  by Lee  Add the support for Arduino Yun board, update the latest UTFT library for ArduCAM.
  2015/06/09  V3.4.1  by Lee  Minor changes and add some comments
  2015/06/19  V3.4.2  by Lee  Add support for MT9M112 camera.
  2015/06/20  V3.4.3  by Lee  Add support for MT9V111 camera.
  2015/06/22  V3.4.4  by Lee  Add support for OV5640 camera.
  2015/06/22  V3.4.5  by Lee  Add support for MT9M001 camera.
  2015/08/05  V3.4.6  by Lee  Add support for MT9T112 camera.
  2015/08/08  V3.4.7  by Lee  Add support for MT9D112 camera.
  2015/09/20  V3.4.8  by Lee  Add support for ESP8266 processor.
  2016/02/03  V3.4.9  by Lee  Add support for Arduino ZERO board.
  2016/06/07  V3.5.0  by Lee  Add support for OV5642_CAM_BIT_ROTATION_FIXED.
  2016/06/14  V3.5.1  by Lee  Add support for ArduCAM-Mini-5MP-Plus OV5640_CAM.
  2016/09/29  V3.5.2  by Lee  Optimize the OV5642 register settings
	2016/10/05	V4.0.0	by Lee	Add support for second generation hardware platforms like ArduCAM shield V2, ArduCAM-Mini-5MP-Plus(OV5642/OV5640).	  
  2016/10/28  V4.0.1  by Lee	Add support for Raspberry Pi
  --------------------------------------*/
#include "memorysaver.h"
#if defined ( RASPBERRY_PI )
	#include <string.h>
	#include <time.h>
	#include <stdio.h>
	#include <stdlib.h>
	#include <stdint.h>
	#include <unistd.h>
	#include <wiringPiI2C.h>
	#include <wiringPi.h>
	#include "ArduCAM.h"
	#include "arducam_arch_raspberrypi.h"
#elif defined (PARTICLE)
    #include "ArduCAM.h"
    #include "Arduino.h"
#else
	#include "Arduino.h"
	#include "ArduCAM.h"
	#include <Wire.h>
	#include <SPI.h>
	#include "HardwareSerial.h"
	#if defined(__SAM3X8E__)
	#define Wire Wire1
	#endif
#endif


ArduCAM::ArduCAM()
{
  sensor_model = OV7670;
  sensor_addr = 0x42;
}
ArduCAM::ArduCAM(byte model ,int CS)
{
	#if defined (RASPBERRY_PI)
	  
		if(CS>=0)
		{
			B_CS = CS;
		}
	#else
		#if defined(ESP8266)
		  B_CS = CS;
		#else
		  P_CS  = portOutputRegister(digitalPinToPort(CS));
		  B_CS  = digitalPinToBitMask(CS);
		#endif
	#endif
 #if defined (RASPBERRY_PI)
   pinMode(CS, OUTPUT);
 #else
	  pinMode(CS, OUTPUT);
      sbi(P_CS, B_CS);
	#endif
	sensor_model = model;
	switch (sensor_model)
	{
		case OV7660:
		case OV7670:
		case OV7675:
		case OV7725:
		#if defined (RASPBERRY_PI)
				sensor_addr = 0x21;
		#else
		  	sensor_addr = 0x42;
	    #endif		
		break;
		case MT9D111_A: //Standard MT9D111 module
      sensor_addr = 0xba;
    break;
    case MT9D111_B: //Flex MT9D111 AF module
      sensor_addr = 0x90;
    break;
    case MT9M112:
    	#if defined (RASPBERRY_PI)
    		sensor_addr = 0x5d;
    	#else
      	sensor_addr = 0x90;
      #endif
    break;
    case MT9M001:
      sensor_addr = 0xba;
    break;
    case OV3640:
    case OV5640:
    case OV5642:
    case MT9T112:
    case MT9D112:
    	#if defined (RASPBERRY_PI)
    		sensor_addr = 0x3c;
    	#else
      	sensor_addr = 0x78;
       #endif
   break;
    case OV2640:
    case OV9650:
    case OV9655:
    	#if defined (RASPBERRY_PI)
    		sensor_addr = 0x30;
    	#else
      	sensor_addr = 0x60;
      #endif
    break;
		default:
			#if defined (RASPBERRY_PI)
		 		sensor_addr = 0x21;
		 	#else
		 		sensor_addr = 0x42;
      #endif
		break;
	}	
	#if defined (RASPBERRY_PI)
		// initialize i2c:
	if (!arducam_i2c_init(sensor_addr)) {
		printf("ERROR: I2C init failed\n");
	}
	#endif
}

void ArduCAM::InitCAM()
{
 
  switch (sensor_model)
  {
    case OV7660:
      {
#if defined OV7660_CAM
        wrSensorReg8_8(0x12, 0x80);
        delay(100);
        wrSensorRegs8_8(OV7660_QVGA);
#endif
        break;
      }
    case OV7725:
      {
#if defined OV7725_CAM
       byte reg_val;
        wrSensorReg8_8(0x12, 0x80);
        delay(100);
        wrSensorRegs8_8(OV7725_QVGA);
        rdSensorReg8_8(0x15, &reg_val);
        wrSensorReg8_8(0x15, (reg_val | 0x02));
#endif
        break;
      }
    case OV7670:
      {
#if defined OV7670_CAM
        wrSensorReg8_8(0x12, 0x80);
        delay(100);
        wrSensorRegs8_8(OV7670_QVGA);
#endif
        break;
      }
    case OV7675:
      {
#if defined OV7675_CAM
        wrSensorReg8_8(0x12, 0x80);
        delay(100);
        wrSensorRegs8_8(OV7675_QVGA);

#endif
        break;
      }
    case MT9D111_A:
    case MT9D111_B:
      {
#if defined MT9D111_CAM
        wrSensorRegs8_16(MT9D111_QVGA_30fps);
        delay(1000);
        wrSensorReg8_16(0x97, 0x0020);
        wrSensorReg8_16(0xf0, 0x00);
        wrSensorReg8_16(0x21, 0x8403); //Mirror Column
        wrSensorReg8_16(0xC6, 0xA103);//SEQ_CMD
        wrSensorReg8_16(0xC8, 0x0005); //SEQ_CMD
#endif
        break;

      }
    case OV5642:
      {
#if ( defined(OV5642_CAM) || defined(OV5642_MINI_5MP) || defined(OV5642_MINI_5MP_BIT_ROTATION_FIXED) || defined(OV5642_MINI_5MP_PLUS) )
        wrSensorReg16_8(0x3008, 0x80);
        wrSensorRegs16_8(OV5642_QVGA_Preview);
        #if defined (RASPBERRY_PI) 
			  arducam_delay_ms(100);
				#else
        delay(100);
        #endif
        if (m_fmt == JPEG)
        {
        	#if defined (RASPBERRY_PI) 
				  arducam_delay_ms(100);
					#else
	        delay(100);
	        #endif
          wrSensorRegs16_8(OV5642_JPEG_Capture_QSXGA);
          wrSensorRegs16_8(ov5642_320x240);
          #if defined (RASPBERRY_PI) 
			  arducam_delay_ms(100);
				#else
        delay(100);
        #endif
          wrSensorReg16_8(0x3818, 0xa8);
          wrSensorReg16_8(0x3621, 0x10);
          wrSensorReg16_8(0x3801, 0xb0);
          #if (defined(OV5642_MINI_5MP_PLUS) || (defined ARDUCAM_SHIELD_V2))
          wrSensorReg16_8(0x4407, 0x04);
          #else
          wrSensorReg16_8(0x4407, 0x0C);
          #endif
        }
        else
        {
        	byte reg_val;
          wrSensorReg16_8(0x4740, 0x21);
          wrSensorReg16_8(0x501e, 0x2a);
          wrSensorReg16_8(0x5002, 0xf8);
          wrSensorReg16_8(0x501f, 0x01);
          wrSensorReg16_8(0x4300, 0x61);
          rdSensorReg16_8(0x3818, &reg_val);
          wrSensorReg16_8(0x3818, (reg_val | 0x60) & 0xff);
          rdSensorReg16_8(0x3621, &reg_val);
          wrSensorReg16_8(0x3621, reg_val & 0xdf);
        }

#endif
        break;
      }
    case OV5640:
      {
#if ( defined(OV5640_CAM) || defined(OV5640_MINI_5MP_PLUS) )
        delay(100);
        if (m_fmt == JPEG)
        {
          wrSensorReg16_8(0x3103, 0x11);
          wrSensorReg16_8(0x3008, 0x82);
          delay(100);
          wrSensorRegs16_8(OV5640YUV_Sensor_Dvp_Init);
          delay(500);
          wrSensorRegs16_8(OV5640_JPEG_QSXGA);
          wrSensorRegs16_8(OV5640_QSXGA2QVGA);
          #if (defined(OV5640_MINI_5MP_PLUS) || (defined ARDUCAM_SHIELD_V2))
          wrSensorReg16_8(0x4407, 0x04);
          #else
          wrSensorReg16_8(0x4407, 0x0C);
          #endif
        }
        else
        {
          wrSensorReg16_8(0x3103, 0x11);
          wrSensorReg16_8(0x3008, 0x82);
          delay(500);
          wrSensorRegs16_8(OV5640YUV_Sensor_Dvp_Init);
          wrSensorRegs16_8(OV5640_RGB_QVGA);
        }

#endif
        break;
      }
    case OV3640:
      {
#if defined OV3640_CAM
        rtn = wrSensorRegs16_8(OV3640_QVGA);
#endif
        break;
      }
    case OV2640:
      {
#if (defined(OV2640_CAM) || defined(OV2640_MINI_2MP))
        wrSensorReg8_8(0xff, 0x01);
        wrSensorReg8_8(0x12, 0x80);
        delay(100);
        if (m_fmt == JPEG)
        {
          wrSensorRegs8_8(OV2640_JPEG_INIT);
          wrSensorRegs8_8(OV2640_YUV422);
          wrSensorRegs8_8(OV2640_JPEG);
          wrSensorReg8_8(0xff, 0x01);
          wrSensorReg8_8(0x15, 0x00);
          wrSensorRegs8_8(OV2640_320x240_JPEG);
          //wrSensorReg8_8(0xff, 0x00);
          //wrSensorReg8_8(0x44, 0x32);
        }
        else
        {
          wrSensorRegs8_8(OV2640_QVGA);
        }
#endif
        break;
      }
    case OV9655:
      {

        break;
      }
    case MT9M112:
      {
#if defined MT9M112_CAM
        wrSensorRegs8_16(MT9M112_QVGA);
#endif
        break;
      }
    case MT9V111:
      {
#if defined MT9V111_CAM
        //Reset sensor core
        wrSensorReg8_16(0x01, 0x04);
        wrSensorReg8_16(0x0D, 0x01);
        wrSensorReg8_16(0x0D, 0x00);
        //Reset IFP
        wrSensorReg8_16(0x01, 0x01);
        wrSensorReg8_16(0x07, 0x01);
        wrSensorReg8_16(0x07, 0x00);
        delay(100);
        wrSensorRegs8_16(MT9V111_QVGA);
        //delay(1000);
        wrSensorReg8_16(0x97, 0x0020);
        wrSensorReg8_16(0xf0, 0x00);
        wrSensorReg8_16(0x21, 0x8403); //Mirror Column
        wrSensorReg8_16(0xC6, 0xA103);//SEQ_CMD
        wrSensorReg8_16(0xC8, 0x0005); //SEQ_CMD
#endif
        break;
      }

    case MT9M001:
      {
#if defined MT9M001_CAM
        wrSensorRegs8_16(MT9M001_QVGA_30fps);
#endif
        break;
      }
    case MT9T112:
      {
#if defined MT9T112_CAM

        wrSensorReg16_16(0x001a , 0x0219 );
        wrSensorReg16_16(0x001a , 0x0018 );
        //reset camera
        wrSensorReg16_16(0x0014 , 0x2425 );
        wrSensorReg16_16(0x0014 , 0x2145 );
        wrSensorReg16_16(0x0010 , 0x0110 );
        wrSensorReg16_16(0x0012 , 0x00f0 );
        wrSensorReg16_16(0x002a , 0x7f77 );
        wrSensorReg16_16(0x0014 , 0x2545 );
        wrSensorReg16_16(0x0014 , 0x2547 );
        wrSensorReg16_16(0x0014 , 0x3447 );
        wrSensorReg16_16(0x0014 , 0x3047 );
        delay(10);
        wrSensorReg16_16(0x0014 , 0x3046 );
        wrSensorReg16_16(0x0022 , 0x01f4 );
        wrSensorReg16_16(0x001e , 0x0707 );
        wrSensorReg16_16(0x3b84 , 0x01f4 );
        wrSensorReg16_16(0x002e , 0x0500 );
        wrSensorReg16_16(0x0018 , 0x402b );
        wrSensorReg16_16(0x3b82 , 0x0004 );
        wrSensorReg16_16(0x0018 , 0x402f );
        wrSensorReg16_16(0x0018 , 0x402e );
        delay(50);
        wrSensorReg16_16(0x0614 , 0x0001 );
        delay(1);
        wrSensorReg16_16(0x0614 , 0x0001 );
        delay(1);
        wrSensorReg16_16(0x0614 , 0x0001 );
        delay(1);
        wrSensorReg16_16(0x0614 , 0x0001 );
        delay(1);
        wrSensorReg16_16(0x0614 , 0x0001 );
        delay(1);
        wrSensorReg16_16(0x0614 , 0x0001 );
        delay(1);
        delay(10);
        //init pll
        wrSensorReg16_16(0x098e , 0x6800 );
        wrSensorReg16_16(0x0990 , 0x0140 );
        wrSensorReg16_16(0x098e , 0x6802 );
        wrSensorReg16_16(0x0990 , 0x00f0 );
        wrSensorReg16_16(0x098e , 0x68a0 );
        wrSensorReg16_16(0x098e , 0x68a0 );
        wrSensorReg16_16(0x0990 , 0x082d );
        wrSensorReg16_16(0x098e , 0x4802 );
        wrSensorReg16_16(0x0990 , 0x0000 );
        wrSensorReg16_16(0x098e , 0x4804 );
        wrSensorReg16_16(0x0990 , 0x0000 );
        wrSensorReg16_16(0x098e , 0x4806 );
        wrSensorReg16_16(0x0990 , 0x060d );
        wrSensorReg16_16(0x098e , 0x4808 );
        wrSensorReg16_16(0x0990 , 0x080d );
        wrSensorReg16_16(0x098e , 0x480c );
        wrSensorReg16_16(0x0990 , 0x046c );
        wrSensorReg16_16(0x098e , 0x480f );
        wrSensorReg16_16(0x0990 , 0x00cc );
        wrSensorReg16_16(0x098e , 0x4811 );
        wrSensorReg16_16(0x0990 , 0x0381 );
        wrSensorReg16_16(0x098e , 0x4813 );
        wrSensorReg16_16(0x0990 , 0x024f );
        wrSensorReg16_16(0x098e , 0x481d );
        wrSensorReg16_16(0x0990 , 0x0436 );
        wrSensorReg16_16(0x098e , 0x481f );
        wrSensorReg16_16(0x0990 , 0x05d0 );
        wrSensorReg16_16(0x098e , 0x4825 );
        wrSensorReg16_16(0x0990 , 0x1153 );
        wrSensorReg16_16(0x098e , 0x6ca0 );
        wrSensorReg16_16(0x098e , 0x6ca0 );
        wrSensorReg16_16(0x0990 , 0x082d );
        wrSensorReg16_16(0x098e , 0x484a );
        wrSensorReg16_16(0x0990 , 0x0004 );
        wrSensorReg16_16(0x098e , 0x484c );
        wrSensorReg16_16(0x0990 , 0x0004 );
        wrSensorReg16_16(0x098e , 0x484e );
        wrSensorReg16_16(0x0990 , 0x060b );
        wrSensorReg16_16(0x098e , 0x4850 );
        wrSensorReg16_16(0x0990 , 0x080b );
        wrSensorReg16_16(0x098e , 0x4857 );
        wrSensorReg16_16(0x0990 , 0x008c );
        wrSensorReg16_16(0x098e , 0x4859 );
        wrSensorReg16_16(0x0990 , 0x01f1 );
        wrSensorReg16_16(0x098e , 0x485b );
        wrSensorReg16_16(0x0990 , 0x00ff );
        wrSensorReg16_16(0x098e , 0x4865 );
        wrSensorReg16_16(0x0990 , 0x0668 );
        wrSensorReg16_16(0x098e , 0x4867 );
        wrSensorReg16_16(0x0990 , 0x0af0 );
        wrSensorReg16_16(0x098e , 0x486d );
        wrSensorReg16_16(0x0990 , 0x0af0 );
        wrSensorReg16_16(0x098e , 0xa005 );
        wrSensorReg16_16(0x0990 , 0x0001 );
        wrSensorReg16_16(0x098e , 0x6c11 );
        wrSensorReg16_16(0x0990 , 0x0003 );
        wrSensorReg16_16(0x098e , 0x6811 );
        wrSensorReg16_16(0x0990 , 0x0003 );
        wrSensorReg16_16(0x098e , 0xc8a5 );
        wrSensorReg16_16(0x0990 , 0x0025 );
        wrSensorReg16_16(0x098e , 0xc8a6 );
        wrSensorReg16_16(0x0990 , 0x0028 );
        wrSensorReg16_16(0x098e , 0xc8a7 );
        wrSensorReg16_16(0x0990 , 0x002c );
        wrSensorReg16_16(0x098e , 0xc8a8 );
        wrSensorReg16_16(0x0990 , 0x002f );
        wrSensorReg16_16(0x098e , 0xc844 );
        wrSensorReg16_16(0x0990 , 0x00ba );
        wrSensorReg16_16(0x098e , 0xc92f );
        wrSensorReg16_16(0x0990 , 0x0000 );
        wrSensorReg16_16(0x098e , 0xc845 );
        wrSensorReg16_16(0x0990 , 0x009b );
        wrSensorReg16_16(0x098e , 0xc92d );
        wrSensorReg16_16(0x0990 , 0x0000 );
        wrSensorReg16_16(0x098e , 0xc88c );
        wrSensorReg16_16(0x0990 , 0x0082 );
        wrSensorReg16_16(0x098e , 0xc930 );
        wrSensorReg16_16(0x0990 , 0x0000 );
        wrSensorReg16_16(0x098e , 0xc88d );
        wrSensorReg16_16(0x0990 , 0x006d );
        wrSensorReg16_16(0x098e , 0xc92e );
        wrSensorReg16_16(0x0990 , 0x0000 );
        wrSensorReg16_16(0x098e , 0xa002 );
        wrSensorReg16_16(0x0990 , 0x0010 );
        wrSensorReg16_16(0x098e , 0xa009 );
        wrSensorReg16_16(0x0990 , 0x0002 );
        wrSensorReg16_16(0x098e , 0xa00a );
        wrSensorReg16_16(0x0990 , 0x0003 );
        wrSensorReg16_16(0x098e , 0xa00c );
        wrSensorReg16_16(0x0990 , 0x000a );
        wrSensorReg16_16(0x098e , 0x4846 );
        wrSensorReg16_16(0x0990 , 0x0014 );
        wrSensorReg16_16(0x098e , 0x488e );
        wrSensorReg16_16(0x0990 , 0x0014 );
        wrSensorReg16_16(0x098e , 0xc844 );
        wrSensorReg16_16(0x0990 , 0x0085 );
        wrSensorReg16_16(0x098e , 0xc845 );
        wrSensorReg16_16(0x0990 , 0x006e );
        wrSensorReg16_16(0x098e , 0xc88c );
        wrSensorReg16_16(0x0990 , 0x0082 );
        wrSensorReg16_16(0x098e , 0xc88d );
        wrSensorReg16_16(0x0990 , 0x006c );
        wrSensorReg16_16(0x098e , 0xc8a5 );
        wrSensorReg16_16(0x0990 , 0x001b );
        wrSensorReg16_16(0x098e , 0xc8a6 );
        wrSensorReg16_16(0x0990 , 0x001e );
        wrSensorReg16_16(0x098e , 0xc8a7 );
        wrSensorReg16_16(0x0990 , 0x0020 );
        wrSensorReg16_16(0x098e , 0xc8a8 );
        wrSensorReg16_16(0x0990 , 0x0023 );
        //init setting
        wrSensorReg16_16(0x0018 , 0x002a );
        wrSensorReg16_16(0x3084 , 0x2409 );
        wrSensorReg16_16(0x3092 , 0x0a49 );
        wrSensorReg16_16(0x3094 , 0x4949 );
        wrSensorReg16_16(0x3096 , 0x4950 );
        wrSensorReg16_16(0x098e , 0x68a0 );
        wrSensorReg16_16(0x0990 , 0x0a2e );
        wrSensorReg16_16(0x098e , 0x6ca0 );
        wrSensorReg16_16(0x0990 , 0x0a2e );
        wrSensorReg16_16(0x098e , 0x6c90 );
        wrSensorReg16_16(0x0990 , 0x0cb4 );
        wrSensorReg16_16(0x098e , 0x6807 );
        wrSensorReg16_16(0x0990 , 0x0004 );
        wrSensorReg16_16(0x098e , 0xe88e );
        wrSensorReg16_16(0x0990 , 0x0000 );
        wrSensorReg16_16(0x316c , 0x350f );
        wrSensorReg16_16(0x001e , 0x0777 );
        wrSensorReg16_16(0x098e , 0x8400 );
        wrSensorReg16_16(0x0990 , 0x0001 );
        delay(100);
        wrSensorReg16_16(0x098e , 0x8400 );
        wrSensorReg16_16(0x0990 , 0x0006 );
        //Serial.println("MT9T112 init done");
#endif
        break;
      }
    case MT9D112:
      {
#if defined MT9D112_CAM
        wrSensorReg16_16(0x301a , 0x0acc );
        wrSensorReg16_16(0x3202 , 0x0008 );
        delay(100 );
        wrSensorReg16_16(0x341e , 0x8f09 );
        wrSensorReg16_16(0x341c , 0x020c );
        delay(100 );
        wrSensorRegs16_16(MT9D112_default_setting);
        wrSensorReg16_16(0x338c , 0xa103 );
        wrSensorReg16_16(0x3390 , 0x0006 );
        delay(100 );
        wrSensorReg16_16(0x338c , 0xa103 );
        wrSensorReg16_16(0x3390 , 0x0005 );
        delay(100 );
        wrSensorRegs16_16(MT9D112_soc_init);
        delay(200);
        wrSensorReg16_16(0x332E, 0x0020); //RGB565

#endif
      }
    default:

      break;
  }
}

void ArduCAM::flush_fifo(void)
{
	write_reg(ARDUCHIP_FIFO, FIFO_CLEAR_MASK);
}

void ArduCAM::start_capture(void)
{
	write_reg(ARDUCHIP_FIFO, FIFO_START_MASK);
}

void ArduCAM::clear_fifo_flag(void )
{
	write_reg(ARDUCHIP_FIFO, FIFO_CLEAR_MASK);
}

uint32_t ArduCAM::read_fifo_length(void)
{
	uint32_t len1,len2,len3,length=0;
	len1 = read_reg(FIFO_SIZE1);
  len2 = read_reg(FIFO_SIZE2);
  len3 = read_reg(FIFO_SIZE3) & 0x7f;
  length = ((len3 << 16) | (len2 << 8) | len1) & 0x07fffff;
	return length;	
}

#if defined (RASPBERRY_PI)
uint8_t ArduCAM::transfer(uint8_t data)
{
  uint8_t temp;
  temp = arducam_spi_transfer(data);
  return temp;
}

void ArduCAM::transfers(uint8_t *buf, uint32_t size)
{
	arducam_spi_transfers(buf, size);
}

#endif

void ArduCAM::set_fifo_burst()
{
	#if defined (RASPBERRY_PI)
	transfer(BURST_FIFO_READ);
	#else
    SPI.transfer(BURST_FIFO_READ);
   #endif
}

void ArduCAM::CS_HIGH(void)
{
	 sbi(P_CS, B_CS);
}
void ArduCAM::CS_LOW(void)
{
	 cbi(P_CS, B_CS);
}

uint8_t ArduCAM::read_fifo(void)
{
	uint8_t data;
	data = bus_read(SINGLE_FIFO_READ);
	return data;
}

uint8_t ArduCAM::read_reg(uint8_t addr)
{
	uint8_t data;
	#if defined (RASPBERRY_PI)
		data = bus_read(addr);	
	#else
		data = bus_read(addr & 0x7F);
	#endif
	return data;
}

void ArduCAM::write_reg(uint8_t addr, uint8_t data)
{
	#if defined (RASPBERRY_PI)
		bus_write(addr , data);
	#else
	 bus_write(addr | 0x80, data);
  #endif  
}

//My add
//Set corresponding bit  
void ArduCAM::set_bit(uint8_t addr, uint8_t bit)
{
	uint8_t temp;
	temp = read_reg(addr);
	write_reg(addr, temp | bit);
}
//Clear corresponding bit 
void ArduCAM::clear_bit(uint8_t addr, uint8_t bit)
{
	uint8_t temp;
	temp = read_reg(addr);
	write_reg(addr, temp & (~bit));
}

//Get corresponding bit status
uint8_t ArduCAM::get_bit(uint8_t addr, uint8_t bit)
{
  uint8_t temp;
  temp = read_reg(addr);
  temp = temp & bit;
  return temp;
}

//Set ArduCAM working mode
//MCU2LCD_MODE: MCU writes the LCD screen GRAM
//CAM2LCD_MODE: Camera takes control of the LCD screen
//LCD2MCU_MODE: MCU read the LCD screen GRAM
void ArduCAM::set_mode(uint8_t mode)
{
  switch (mode)
  {
    case MCU2LCD_MODE:
      write_reg(ARDUCHIP_MODE, MCU2LCD_MODE);
      break;
    case CAM2LCD_MODE:
      write_reg(ARDUCHIP_MODE, CAM2LCD_MODE);
      break;
    case LCD2MCU_MODE:
      write_reg(ARDUCHIP_MODE, LCD2MCU_MODE);
      break;
    default:
      write_reg(ARDUCHIP_MODE, MCU2LCD_MODE);
      break;
  }
}

uint8_t ArduCAM::bus_write(int address,int value)
{
#if defined (PARTICLE)
  SPI.beginTransaction(SPISettings(8*MHZ, MSBFIRST, SPI_MODE0));
#endif

	cbi(P_CS, B_CS);
	#if defined (RASPBERRY_PI)
		arducam_spi_write(address | 0x80, value);
	#else
		SPI.transfer(address);
		SPI.transfer(value);
	#endif
	sbi(P_CS, B_CS);

#if defined (PARTICLE)
	SPI.endTransaction();
#endif

	return 1;
}

uint8_t ArduCAM:: bus_read(int address)
{
#if defined (PARTICLE)
  SPI.beginTransaction(SPISettings(8*MHZ, MSBFIRST, SPI_MODE0));
#endif

	uint8_t value;
	cbi(P_CS, B_CS);
	#if defined (RASPBERRY_PI)
		value = arducam_spi_read(address & 0x7F);
		sbi(P_CS, B_CS);
		#if defined (PARTICLE)
            SPI.endTransaction();
        #endif

		return value;	
	#else
		#if (defined(ESP8266) || defined(__arm__))
		#if defined(OV5642_MINI_5MP)
		  SPI.transfer(address);
		  value = SPI.transfer(0x00);
		  // correction for bit rotation from readback
		  value = (byte)(value >> 1) | (value << 7);
		  // take the SS pin high to de-select the chip:
		  sbi(P_CS, B_CS);
		  #if defined (PARTICLE)
                SPI.endTransaction();
            #endif
		  return value;
		#else
		  SPI.transfer(address);
		  value = SPI.transfer(0x00);
		  // take the SS pin high to de-select the chip:
		  sbi(P_CS, B_CS);
		  #if defined (PARTICLE)
                SPI.endTransaction();
            #endif
		  return value;
		#endif
		#else
		  SPI.transfer(address);
		  value = SPI.transfer(0x00);
		  // take the SS pin high to de-select the chip:
		  sbi(P_CS, B_CS);
		  #if defined (PARTICLE)
                SPI.endTransaction();
            #endif
		  return value;
		#endif
#endif
}



void ArduCAM::OV2640_set_JPEG_size(uint8_t size)
{
 #if (defined (OV2640_CAM)||defined (OV2640_MINI_2MP))
	switch(size)
	{
		case OV2640_160x120:
			wrSensorRegs8_8(OV2640_160x120_JPEG);
			break;
		case OV2640_176x144:
			wrSensorRegs8_8(OV2640_176x144_JPEG);
			break;
		case OV2640_320x240:
			wrSensorRegs8_8(OV2640_320x240_JPEG);
			break;
		case OV2640_352x288:
	  	wrSensorRegs8_8(OV2640_352x288_JPEG);
			break;
		case OV2640_640x480:
			wrSensorRegs8_8(OV2640_640x480_JPEG);
			break;
		case OV2640_800x600:
			wrSensorRegs8_8(OV2640_800x600_JPEG);
			break;
		case OV2640_1024x768:
			wrSensorRegs8_8(OV2640_1024x768_JPEG);
			break;
		case OV2640_1280x1024:
			wrSensorRegs8_8(OV2640_1280x1024_JPEG);
			break;
		case OV2640_1600x1200:
			wrSensorRegs8_8(OV2640_1600x1200_JPEG);
			break;
		default:
			wrSensorRegs8_8(OV2640_320x240_JPEG);
			break;
	}
#endif
}

void ArduCAM::OV5642_set_JPEG_size(uint8_t size)
{
#if defined(OV5642_CAM) || defined(OV5642_CAM_BIT_ROTATION_FIXED)|| defined(OV5642_MINI_5MP) || defined (OV5642_MINI_5MP_PLUS)
  uint8_t reg_val;

  switch (size)
  {
    case OV5642_320x240:
      wrSensorRegs16_8(ov5642_320x240);
      break;
    case OV5642_640x480:
      wrSensorRegs16_8(ov5642_640x480);
      break;
    case OV5642_1024x768:
      wrSensorRegs16_8(ov5642_1024x768);
      break;
    case OV5642_1280x960:
      wrSensorRegs16_8(ov5642_1280x960);
      break;
    case OV5642_1600x1200:
      wrSensorRegs16_8(ov5642_1600x1200);
      break;
    case OV5642_2048x1536:
      wrSensorRegs16_8(ov5642_2048x1536);
      break;
    case OV5642_2592x1944:
      wrSensorRegs16_8(ov5642_2592x1944);
      break;
    default:
      wrSensorRegs16_8(ov5642_320x240);
      break;
  }
#endif
}


void ArduCAM::OV5640_set_JPEG_size(uint8_t size)
{
#if (defined (OV5640_CAM)||defined (OV5640_MINI_5MP_PLUS))
  switch (size)
  {
    case OV5640_320x240:
      wrSensorRegs16_8(OV5640_QSXGA2QVGA);
      break;
    case OV5640_352x288:
      wrSensorRegs16_8(OV5640_QSXGA2CIF);
      break;
    case OV5640_640x480:
      wrSensorRegs16_8(OV5640_QSXGA2VGA);
      break;
    case OV5640_800x480:
      wrSensorRegs16_8(OV5640_QSXGA2WVGA);
      break;
    case OV5640_1024x768:
      wrSensorRegs16_8(OV5640_QSXGA2XGA);
      break;
    case OV5640_1280x960:
      wrSensorRegs16_8(OV5640_QSXGA2SXGA);
      break;
    case OV5640_1600x1200:
      wrSensorRegs16_8(OV5640_QSXGA2UXGA);
      break;
    case OV5640_2048x1536:
      wrSensorRegs16_8(OV5640_QSXGA2QXGA);
      break;
    case OV5640_2592x1944:
      wrSensorRegs16_8(OV5640_JPEG_QSXGA);
      break;
    default:
      //320x240
      wrSensorRegs16_8(OV5640_QSXGA2QVGA);
      break;
  }
#endif

}

void ArduCAM::set_format(byte fmt)
{
  if (fmt == BMP)
    m_fmt = BMP;
  else
    m_fmt = JPEG;
}
	// Write 8 bit values to 8 bit register address
int ArduCAM::wrSensorRegs8_8(const struct sensor_reg reglist[])
{
	#if defined (RASPBERRY_PI)
		arducam_i2c_write_regs(reglist);
	#else
		int err = 0;
	  uint16_t reg_addr = 0;
	  uint16_t reg_val = 0;
	  const struct sensor_reg *next = reglist;
	  while ((reg_addr != 0xff) | (reg_val != 0xff))
	  {
	    reg_addr = pgm_read_word(&next->reg);
	    reg_val = pgm_read_word(&next->val);
	    err = wrSensorReg8_8(reg_addr, reg_val);
	    next++;
		#if defined(ESP8266)
		    yield();
		#endif
	  }
 #endif  
	return 1;
}

	// Write 16 bit values to 8 bit register address
int ArduCAM::wrSensorRegs8_16(const struct sensor_reg reglist[])
{
	#if defined (RASPBERRY_PI)
		arducam_i2c_write_regs16(reglist);
	#else
		int err = 0;
	  unsigned int reg_addr, reg_val;
	  const struct sensor_reg *next = reglist;
	
	  while ((reg_addr != 0xff) | (reg_val != 0xffff))
	  {
	  	#if defined (RASPBERRY_PI)
...

This file has been truncated, please download it to see its full contents.

PIRSensor.ino

C/C++
// Sketch for Particle Photon - PIR Sensor / Motion Detection

int inputPin = D0;              // choose the input pin (for PIR sensor)
int ledPin = D1;                // LED Pin
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status
int ActivityFrequency = 0;
int ActivityFrequency1 = 0;
int count = 0;

int calibrateTime = 10000;      // wait for the thingy to calibrate
//Timer timer(6000, updateThingspeak);
const String key = "your key here"; //thingspeak write key

void setup() {
    pinMode(ledPin, OUTPUT);
    pinMode(inputPin, INPUT);     // declare sensor as input

    Particle.subscribe("status_start", camstart, "27003d000d47343438323536" );
    //Particle.subscribe("status_done", camdone, "27003d000d47343438323536" );
    //timer.start();
}



void loop() {

  // if the sensor is calibrated
  if (calibrated()) {
  // get the data from the sensor
    readTheSensor();

    // report it out, if the state has changed
    reportTheData();
    }
}

void readTheSensor() {
    val = digitalRead(inputPin);
}

bool calibrated() {
    return millis() - calibrateTime > 0;



}



void setLED(int state) {
    digitalWrite(ledPin, state);
}

void camstart(const char *event, const char *data) {
    ActivityFrequency = atof(data);
    }


void reportTheData() {
    if (val == HIGH) {
        // the current state is no motion
        // i.e. it's just changed
        // announce this change by publishing an event
        if (pirState == LOW) {
          // we have just turned on
          Particle.publish("KN_motion", "Motion Detected", PUBLIC);
          // Update the current state
            count++;
            Serial.print("Updating Thingspeak:");
            Serial.print(count);
          Particle.publish("activity frequency", String(ActivityFrequency));
          Particle.publish("thingSpeakWrite_All", +
          "{ \"1\": \"" + String(ActivityFrequency) + "\"," +
          "\"k\": \"" + key + "\" }", 60, PRIVATE);
          
          pirState = HIGH;
          setLED(pirState);
          delay (5*1000);
          pirState = LOW;

          
            if (ActivityFrequency == 1) {
             delay (1000);
                  Particle.publish("delay", "Delaying for image to process", PUBLIC);  //prevent publishing more often than once every 10 seconds
                  val == LOW;
                  setLED(LOW);
                  
        }
    } else {
          //if (pirState == HIGH)
          // we have just turned off
          // Update the current state
          //Particle.publish("KN_motion", "Off", PRIVATE);
          ActivityFrequency1 = 0;
          pirState = LOW;
          setLED(pirState);
        }
        }
        

        }

ArduCam.h

C/C++
/*
  ArduCAM.h - Arduino library support for CMOS Image Sensor
  Copyright (C)2011-2015 ArduCAM.com. All right reserved
  
  Basic functionality of this library are based on the demo-code provided by
  ArduCAM.com. You can find the latest version of the library at
  http://www.ArduCAM.com

  Now supported controllers:
		- OV7670
		- MT9D111
		- OV7675
		- OV2640
		- OV3640
		- OV5642
		- OV5640
		- OV7660
		- OV7725
		- MT9M112		
		- MT9V111
		- OV5640		
		- MT9M001			
		- MT9T112
		- MT9D112
				
	We will add support for many other sensors in next release.
	
  Supported MCU platform
 		-	Theoretically support all Arduino families
  		-	Arduino UNO R3			(Tested)
  		-	Arduino MEGA2560 R3		(Tested)
  		-	Arduino Leonardo R3		(Tested)
  		-	Arduino Nano			(Tested)
  		-	Arduino DUE				(Tested)
  		- Arduino Yun				(Tested)  		
  		-	Raspberry Pi			(Tested)
  		- ESP8266-12				(Tested)  		

  If you make any modifications or improvements to the code, I would appreciate
  that you share the code with me so that I might include it in the next release.
  I can be contacted through http://www.ArduCAM.com

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/*------------------------------------
	Revision History:
	2012/09/20 	V1.0.0	by Lee	first release 
	2012/10/23  V1.0.1  by Lee  Resolved some timing issue for the Read/Write Register	
	2012/11/29	V1.1.0	by Lee  Add support for MT9D111 sensor
	2012/12/13	V1.2.0	by Lee	Add support for OV7675 sensor
	2012/12/28  V1.3.0	by Lee	Add support for OV2640,OV3640,OV5642 sensors
	2013/02/26	V2.0.0	by Lee	New Rev.B shield hardware, add support for FIFO control 
															and support Mega1280/2560 boards 
	2013/05/28	V2.1.0	by Lee	Add support all drawing functions derived from UTFT library 			
	2013/08/24	V3.0.0	by Lee	Support ArudCAM shield Rev.C hardware, features SPI interface and low power mode.
								Support almost all series of Arduino boards including DUE.	
	2014/03/09  V3.1.0  by Lee  Add the more impressive example sketches. 
								Optimise the OV5642 settings, improve image quality.
								Add live preview before JPEG capture.
								Add play back photos one by one	after BMP capture.
	2014/05/01  V3.1.1  by Lee  Minor changes to add support Arduino IDE for linux distributions.	
	2014/09/30  V3.2.0  by Lee  Improvement on OV5642 camera dirver.			
	2014/10/06  V3.3.0  by Lee  Add OV7660,OV7725 camera support.			
	2015/02/27  V3.4.0  by Lee  Add the support for Arduino Yun board, update the latest UTFT library for ArduCAM.			
	2015/06/09  V3.4.1  by Lee	Minor changes and add some comments		
	2015/06/19  V3.4.2  by Lee	Add support for MT9M112 camera.			
	2015/06/20  V3.4.3  by Lee	Add support for MT9V111 camera.			
	2015/06/22  V3.4.4  by Lee	Add support for OV5640 camera.										
	2015/06/22  V3.4.5  by Lee	Add support for MT9M001 camera.		
	2015/08/05  V3.4.6  by Lee	Add support for MT9T112 camera.	
	2015/08/08  V3.4.7  by Lee	Add support for MT9D112 camera.							
	2015/09/20  V3.4.8  by Lee	Add support for ESP8266 processor.	
	2016/02/03	V3.4.9	by Lee	Add support for Arduino ZERO board.
	2016/06/07  V3.5.0  by Lee	Add support for OV5642_CAM_BIT_ROTATION_FIXED.
	2016/06/14  V3.5.1  by Lee	Add support for ArduCAM-Mini-5MP-Plus OV5640_CAM.	
	2016/09/29	V3.5.2	by Lee	Optimize the OV5642 register settings		
	2016/10/05	V4.0.0	by Lee	Add support for second generation of ArduCAM shield V2, ArduCAM-Mini-5MP-Plus(OV5642/OV5640).				
    2016/10/28  V4.0.1  by Lee	Add support for Raspberry Pi.
	2017/01/22  V4.0.2  by Lee	Add support for OV3640 camera.
--------------------------------------*/

#ifndef ArduCAM_H
#define ArduCAM_H
#include "memorysaver.h"

#if defined ( RASPBERRY_PI )
#elif defined ( PARTICLE )
    #include "application.h"
    #include "Arduino.h"
#else
	#include "Arduino.h"
	#include <pins_arduino.h>
	#include "memorysaver.h"
#endif

#if defined (__AVR__)
#define cbi(reg, bitmask) *reg &= ~bitmask
#define sbi(reg, bitmask) *reg |= bitmask
#define pulse_high(reg, bitmask) sbi(reg, bitmask); cbi(reg, bitmask);
#define pulse_low(reg, bitmask) cbi(reg, bitmask); sbi(reg, bitmask);
#define cport(port, data) port &= data
#define sport(port, data) port |= data
#define swap(type, i, j) {type t = i; i = j; j = t;}
#define fontbyte(x) pgm_read_byte(&cfont.font[x])  
#define regtype volatile uint8_t
#define regsize uint8_t
#endif

#if defined(__SAM3X8E__)

#define cbi(reg, bitmask) *reg &= ~bitmask
#define sbi(reg, bitmask) *reg |= bitmask

#define pulse_high(reg, bitmask) sbi(reg, bitmask); cbi(reg, bitmask);
#define pulse_low(reg, bitmask) cbi(reg, bitmask); sbi(reg, bitmask);

#define cport(port, data) port &= data
#define sport(port, data) port |= data

#define swap(type, i, j) {type t = i; i = j; j = t;}
#define fontbyte(x) cfont.font[x]  

#define regtype volatile uint32_t
#define regsize uint32_t

#define PROGMEM

#define pgm_read_byte(x)        (*((char *)x))
#define pgm_read_word(x)        ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
#define pgm_read_byte_near(x)   (*((char *)x))
#define pgm_read_byte_far(x)    (*((char *)x))
#define pgm_read_word_near(x)   ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
#define pgm_read_word_far(x)    ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x))))
#define PSTR(x)  x
#if defined F
	#undef F
#endif
#define F(X) (X)	
#endif	

#if defined(ESP8266)
	#define cbi(reg, bitmask) digitalWrite(bitmask, LOW)
	#define sbi(reg, bitmask) digitalWrite(bitmask, HIGH)
	#define pulse_high(reg, bitmask) sbi(reg, bitmask); cbi(reg, bitmask);
	#define pulse_low(reg, bitmask) cbi(reg, bitmask); sbi(reg, bitmask);
	
	#define cport(port, data) port &= data
	#define sport(port, data) port |= data
	
	#define swap(type, i, j) {type t = i; i = j; j = t;}
	
	#define fontbyte(x) cfont.font[x]  
	
	#define regtype volatile uint32_t
	#define regsize uint32_t
#endif	

#if defined(__CPU_ARC__)
	#define cbi(reg, bitmask) *reg &= ~bitmask
	#define sbi(reg, bitmask) *reg |= bitmask
	#define pulse_high(reg, bitmask) sbi(reg, bitmask); cbi(reg, bitmask);
	#define pulse_low(reg, bitmask) cbi(reg, bitmask); sbi(reg, bitmask);
	#define cport(port, data) port &= data
	#define sport(port, data) port |= data
	#define swap(type, i, j) {type t = i; i = j; j = t;}
	#define fontbyte(x) pgm_read_byte(&cfont.font[x])  
	#define regtype volatile uint32_t
	#define regsize uint32_t
#endif




#if defined(__arm__)



#if defined (PARTICLE)
  #define regtype volatile uint32_t
  #define regsize uint32_t

  //workaround for the deferencing issue, fix when issue is resolved.
//  #define sbi(sfr, bit) ((*sfr) |= _BV(bit))
//  #define cbi(sfr, bit) ((*sfr) &= ~_BV(bit))

  //big hack here
  #define pinLO(_pin) (PIN_MAP[_pin].gpio_peripheral->BSRRH = PIN_MAP[_pin].gpio_pin)
  #define pinHI(_pin) (PIN_MAP[_pin].gpio_peripheral->BSRRL = PIN_MAP[_pin].gpio_pin)
  #define cbi(_pin, bit)                 pinLO(A2)
  #define sbi(_pin, bit)                 pinHI(A2)

#elif defined (RASPBERRY_PI)
	#define regtype volatile uint32_t
	#define regsize uint32_t 
	#define byte uint8_t
	#define cbi(reg, bitmask) digitalWrite(bitmask, LOW)
  #define sbi(reg, bitmask) digitalWrite(bitmask, HIGH)
  #define PROGMEM
	#define PSTR(x)  x
	#if defined F
	#undef F
	#endif
	#define F(X) (X)
#else

#define cbi(reg, bitmask) *reg &= ~bitmask
#define sbi(reg, bitmask) *reg |= bitmask
#define pulse_high(reg, bitmask) sbi(reg, bitmask); cbi(reg, bitmask);
#define pulse_low(reg, bitmask) cbi(reg, bitmask); sbi(reg, bitmask);

#define cport(port, data) port &= data
#define sport(port, data) port |= data

#define swap(type, i, j) {type t = i; i = j; j = t;}

#define fontbyte(x) cfont.font[x]  

#define regtype volatile uint32_t
#define regsize uint32_t
#define PROGMEM

    #define pgm_read_byte(x)        (*((char *)x))
//  #define pgm_read_word(x)        (*((short *)(x & 0xfffffffe)))
    #define pgm_read_word(x)        ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
    #define pgm_read_byte_near(x)   (*((char *)x))
    #define pgm_read_byte_far(x)    (*((char *)x))
//  #define pgm_read_word_near(x)   (*((short *)(x & 0xfffffffe))
//  #define pgm_read_word_far(x)    (*((short *)(x & 0xfffffffe)))
    #define pgm_read_word_near(x)   ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
    #define pgm_read_word_far(x)    ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x))))
    #define PSTR(x)  x
  #if defined F
    #undef F
  #endif
  #define F(X) (X)
 #endif 
#endif	





/****************************************************/
/* Sensor related definition 												*/
/****************************************************/
#define BMP 	0
#define JPEG	1
#define RAW 	2

#define OV7670		0	
#define MT9D111_A	1
#define OV7675		2
#define OV5642		3
#define OV3640  	4
#define OV2640  	5
#define OV9655		6
#define MT9M112		7
#define OV7725		8
#define OV7660		9
#define MT9M001 	10
#define OV5640 		11
#define MT9D111_B	12
#define OV9650		13
#define MT9V111		14
#define MT9T112		15
#define MT9D112		16

#define OV2640_160x120 		0	//160x120
#define OV2640_176x144 		1	//176x144
#define OV2640_320x240 		2	//320x240
#define OV2640_352x288 		3	//352x288
#define OV2640_640x480		4	//640x480
#define OV2640_800x600 		5	//800x600
#define OV2640_1024x768		6	//1024x768
#define OV2640_1280x1024	7	//1280x1024
#define OV2640_1600x1200	8	//1600x1200


#define OV3640_176x144 		0	//176x144
#define OV3640_320x240 		1	//320x240
#define OV3640_352x288 		2	//352x288
#define OV3640_640x480		3	//640x480
#define OV3640_800x600 		4	//800x600
#define OV3640_1024x768		5	//1024x768
#define OV3640_1280x960	    6	//1280x1024
#define OV3640_1600x1200	7	//1600x1200
#define OV3640_2048x1536	8	//2048x1536

#define OV5642_320x240 		0	//320x240
#define OV5642_640x480		1	//640x480
#define OV5642_1024x768		2	//1024x768
#define OV5642_1280x960 	3	//1280x960
#define OV5642_1600x1200	4	//1600x1200
#define OV5642_2048x1536	5	//2048x1536
#define OV5642_2592x1944	6	//2592x1944
#define OV5642_1920x1080	7 //1920x1080

#define OV5640_320x240 		0	//320x240 
#define OV5640_352x288		1	//352x288
#define OV5640_640x480 	    2	//640x480
#define OV5640_800x480	    3	//800x480
#define OV5640_1024x768	    4	//1024x768
#define OV5640_1280x960	    5	//1280x960	
#define OV5640_1600x1200	6	 //1600x1200
#define OV5640_2048x1536	7  //2048x1536
#define OV5640_2592x1944	8	 //2592x1944



//Light Mode

#define Auto                 0
#define Sunny                1
#define Cloudy               2
#define Office               3
#define Home                 4

//Color Saturation 

#define Saturation4          0
#define Saturation3          1
#define Saturation2          2
#define Saturation1          3
#define Saturation0          4

//Brightness

#define Brightbess4          0
#define Brightbess3          1
#define Brightbess2          2
#define Brightbess1          3
#define Brightbess0          4

//Contrast

#define Contrast4            0
#define Contrast3            1
#define Contrast2            2
#define Contrast1            3
#define Contrast0            4

//Special effects

#define Antique              0
#define Bluish               1
#define Greenish             2
#define Reddish              3
#define BW                   4
#define Negative             5
#define BWnegative           6
#define Normal               7



/****************************************************/
/* I2C Control Definition 													*/
/****************************************************/
#define I2C_ADDR_8BIT 0
#define I2C_ADDR_16BIT 1
#define I2C_REG_8BIT 0
#define I2C_REG_16BIT 1
#define I2C_DAT_8BIT 0
#define I2C_DAT_16BIT 1

/* Register initialization tables for SENSORs */
/* Terminating list entry for reg */
#define SENSOR_REG_TERM_8BIT                0xFF
#define SENSOR_REG_TERM_16BIT               0xFFFF
/* Terminating list entry for val */
#define SENSOR_VAL_TERM_8BIT                0xFF
#define SENSOR_VAL_TERM_16BIT               0xFFFF

//Define maximum frame buffer size
#if (defined OV2640_MINI_2MP)
#define MAX_FIFO_SIZE		0x5FFFF			//384KByte
#elif (defined OV5642_MINI_5MP || defined OV5642_MINI_5MP_BIT_ROTATION_FIXED || defined ARDUCAM_SHIELD_REVC )//||defined OV3640_MINI_3MP)
#define MAX_FIFO_SIZE		0x7FFFF			//512KByte
#else
#define MAX_FIFO_SIZE		0x7FFFFF		//8MByte
#endif 

/****************************************************/
/* ArduChip registers definition 											*/
/****************************************************/
#define RWBIT									0x80  //READ AND WRITE BIT IS BIT[7]

#define ARDUCHIP_TEST1       	0x00  //TEST register

#if !(defined OV2640_MINI_2MP)
	#define ARDUCHIP_FRAMES			  0x01  //FRAME control register, Bit[2:0] = Number of frames to be captured																		//On 5MP_Plus platforms bit[2:0] = 7 means continuous capture until frame buffer is full
#endif

#define ARDUCHIP_MODE      		0x02  //Mode register
#define MCU2LCD_MODE       		0x00
#define CAM2LCD_MODE       		0x01
#define LCD2MCU_MODE       		0x02

#define ARDUCHIP_TIM       		0x03  //Timming control
#if !(defined OV2640_MINI_2MP)
	#define HREF_LEVEL_MASK    		0x01  //0 = High active , 		1 = Low active
	#define VSYNC_LEVEL_MASK   		0x02  //0 = High active , 		1 = Low active
	#define LCD_BKEN_MASK      		0x04  //0 = Enable, 					1 = Disable
	#if (defined ARDUCAM_SHIELD_V2)
		#define PCLK_REVERSE_MASK  	0x08  //0 = Normal PCLK, 		1 = REVERSED PCLK
	#else
		#define PCLK_DELAY_MASK  		0x08  //0 = data no delay,		1 = data delayed one PCLK
	#endif
	//#define MODE_MASK          		0x10  //0 = LCD mode, 				1 = FIFO mode
#endif
//#define FIFO_PWRDN_MASK	   		0x20  	//0 = Normal operation, 1 = FIFO power down
//#define LOW_POWER_MODE			  0x40  	//0 = Normal mode, 			1 = Low power mode

#define ARDUCHIP_FIFO      		0x04  //FIFO and I2C control
#define FIFO_CLEAR_MASK    		0x01
#define FIFO_START_MASK    		0x02
#define FIFO_RDPTR_RST_MASK     0x10
#define FIFO_WRPTR_RST_MASK     0x20

#define ARDUCHIP_GPIO			  0x06  //GPIO Write Register
#if !(defined (ARDUCAM_SHIELD_V2) || defined (ARDUCAM_SHIELD_REVC))
#define GPIO_RESET_MASK			0x01  //0 = Sensor reset,							1 =  Sensor normal operation
#define GPIO_PWDN_MASK			0x02  //0 = Sensor normal operation, 	1 = Sensor standby
#define GPIO_PWREN_MASK			0x04	//0 = Sensor LDO disable, 			1 = sensor LDO enable
#endif

#define BURST_FIFO_READ			0x3C  //Burst FIFO read operation
#define SINGLE_FIFO_READ		0x3D  //Single FIFO read operation

#define ARDUCHIP_REV       		0x40  //ArduCHIP revision
#define VER_LOW_MASK       		0x3F
#define VER_HIGH_MASK      		0xC0

#define ARDUCHIP_TRIG      		0x41  //Trigger source
#define VSYNC_MASK         		0x01
#define SHUTTER_MASK       		0x02
#define CAP_DONE_MASK      		0x08

#define FIFO_SIZE1				0x42  //Camera write FIFO size[7:0] for burst to read
#define FIFO_SIZE2				0x43  //Camera write FIFO size[15:8]
#define FIFO_SIZE3				0x44  //Camera write FIFO size[18:16]


/****************************************************/


/****************************************************************/
/* define a structure for sensor register initialization values */
/****************************************************************/
struct sensor_reg {
	uint16_t reg;
	uint16_t val;
};



/****************************************************************/
/* define a structure for sensor register initialization values */
/****************************************************************/

class ArduCAM 
{
	public:
	ArduCAM( void );
	ArduCAM(byte model ,int CS);
	void InitCAM( void );
	
	void CS_HIGH(void);
	void CS_LOW(void);
	
	void flush_fifo(void);
	void start_capture(void);
	void clear_fifo_flag(void);
	uint8_t read_fifo(void);
	
	uint8_t read_reg(uint8_t addr);
	void write_reg(uint8_t addr, uint8_t data);	
	
	uint32_t read_fifo_length(void);
	void set_fifo_burst(void);
	
	void set_bit(uint8_t addr, uint8_t bit);
	void clear_bit(uint8_t addr, uint8_t bit);
	uint8_t get_bit(uint8_t addr, uint8_t bit);
	void set_mode(uint8_t mode);
 
    uint8_t bus_write(int address, int value);
	uint8_t bus_read(int address);	
 
	// Write 8 bit values to 8 bit register address
	int wrSensorRegs8_8(const struct sensor_reg*);
	
	// Write 16 bit values to 8 bit register address
	int wrSensorRegs8_16(const struct sensor_reg*);
	
	// Write 8 bit values to 16 bit register address
	int wrSensorRegs16_8(const struct sensor_reg*);
	
  // Write 16 bit values to 16 bit register address
	int wrSensorRegs16_16(const struct sensor_reg*);
	
	// Read/write 8 bit value to/from 8 bit register address	
	byte wrSensorReg8_8(int regID, int regDat);
	byte rdSensorReg8_8(uint8_t regID, uint8_t* regDat);
	
	// Read/write 16 bit value to/from 8 bit register address
	byte wrSensorReg8_16(int regID, int regDat);
	byte rdSensorReg8_16(uint8_t regID, uint16_t* regDat);
	
	// Read/write 8 bit value to/from 16 bit register address
	byte wrSensorReg16_8(int regID, int regDat);
	byte rdSensorReg16_8(uint16_t regID, uint8_t* regDat);
	
	// Read/write 16 bit value to/from 16 bit register address
	byte wrSensorReg16_16(int regID, int regDat);
	byte rdSensorReg16_16(uint16_t regID, uint16_t* regDat);

	void OV2640_set_JPEG_size(uint8_t size);
	void OV3640_set_JPEG_size(uint8_t size);
	void OV5642_set_JPEG_size(uint8_t size);
	void OV5640_set_JPEG_size(uint8_t size);
	void OV5642_set_RAW_size (uint8_t size);
	
	void set_Light_Mode(uint8_t Light_Mode);
	void set_Color_Saturation(uint8_t Color_Saturation);
	void set_Brightness(uint8_t Brightness);
	void set_Contrast(uint8_t Contrast);
	void set_Special_effects(uint8_t Special_effect);
	
	void set_format(byte fmt);
	
	
	
	
	#if defined (RASPBERRY_PI)
    uint8_t transfer(uint8_t data);
	void transfers(uint8_t *buf, uint32_t size);
    #endif

	void transferBytes_(uint8_t * out, uint8_t * in, uint8_t size);
	void transferBytes(uint8_t * out, uint8_t * in, uint32_t size);
	inline void setDataBits(uint16_t bits);
	
  protected:
	regtype *P_CS;
	regsize B_CS;
	byte m_fmt;
	byte sensor_model;
	byte sensor_addr;
};

#if defined OV7660_CAM	
	#include "ov7660_regs.h"
#endif

#if defined OV7725_CAM	
	#include "ov7725_regs.h"
#endif

#if defined OV7670_CAM	
	#include "ov7670_regs.h"
#endif

#if defined OV7675_CAM
	#include "ov7675_regs.h"
#endif

#if ( defined(OV5642_CAM) || defined(OV5642_MINI_5MP) || defined(OV5642_MINI_5MP_BIT_ROTATION_FIXED) || defined(OV5642_MINI_5MP_PLUS) )	
	#include "ov5642_regs.h"
#endif

#if (defined(OV3640_CAM) || defined(OV3640_MINI_3MP))
	#include "ov3640_regs.h"
#endif

#if (defined(OV2640_CAM) || defined(OV2640_MINI_2MP))
	#include "ov2640_regs.h"
#endif

#if (defined (MT9D111A_CAM) || defined (MT9D111B_CAM))	
	#include "mt9d111_regs.h"
#endif

#if defined MT9M112_CAM	
	#include "mt9m112_regs.h"
#endif

#if defined MT9V111_CAM	
	#include "mt9v111_regs.h"
#endif

#if ( defined(OV5640_CAM)	|| defined(OV5640_MINI_5MP_PLUS) )
	#include "ov5640_regs.h"
#endif

#if defined MT9M001_CAM	
	#include "mt9m001_regs.h"
#endif

#if defined MT9T112_CAM	
	#include "mt9t112_regs.h"
#endif

#if defined MT9D112_CAM	
	#include "mt9d112_regs.h"
#endif



#endif

memorysaver.h

C/C++
#ifndef _MEMORYSAVER_
#define _MEMORYSAVER_

//Only when using raspberry,enable it
//#define RASPBERRY_PI

//There are two steps you need to modify in this file before normal compilation
//Only ArduCAM Shield series platform need to select camera module, ArduCAM-Mini series platform doesn't

//Step 1: select the hardware platform, only one at a time
//#define OV2640_MINI_2MP
//#define OV5642_MINI_5MP
//#define OV5642_MINI_5MP_BIT_ROTATION_FIXED
#define OV5642_MINI_5MP_PLUS
//#define OV5640_MINI_5MP_PLUS

//#define ARDUCAM_SHIELD_REVC
//#define ARDUCAM_SHIELD_V2


//Step 2: Select one of the camera module, only one at a time
#if (defined(ARDUCAM_SHIELD_REVC) || defined(ARDUCAM_SHIELD_V2))
	//#define OV7660_CAM
	//#define OV7725_CAM
	//#define OV7670_CAM
	//#define OV7675_CAM
    //#define OV2640_CAM
	//#define OV3640_CAM
	 #define OV5642_CAM
	//#define OV5640_CAM 
	
	//#define MT9D111A_CAM
	//#define MT9D111B_CAM
	//#define MT9M112_CAM
	//#define MT9V111_CAM	
	//#define MT9M001_CAM	
	//#define MT9T112_CAM
	//#define MT9D112_CAM
#endif 

#endif	//_MEMORYSAVER_

ArduCam / Particle Firmware and Server Repository

Used to configure the ArduCam / Photon to save media to your personal computer. Some changes must be made to these files - see more in the program description.

Moment.js Repository

Time manipulator required for java script. http://momentjs.com/

Credits

Carrie Cohlmia

Carrie Cohlmia

1 project • 1 follower
William Neal

William Neal

1 project • 1 follower

Comments