/*
ArduCam OSD - The Arduino based Remote Camera Control and OSD.
File : ArduCamOSD_Beta.pde
Version : v0.95, 17 may 2011
Author(s): Sandro Benigno
FastSerial and BetterStream from Michael Smith
USB host and PTP library from Oleg Mazurov - circuitsathome.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see .
*/
#include
#undef PROGMEM
#define PROGMEM __attribute__(( section(".progmem.data") ))
#undef PSTR
#define PSTR(s) (__extension__({static prog_char __c[] PROGMEM = (s); &__c[0];}))
#include
#include
#include
#include "Spi.h"
#include "Wire.h" //Future i2c comunication. Uncommented to watch hex size
/****** USB INCLUDES ******/
#include
#include
#include
#include
#include
#include
#include
#include "pseventparser.h"
#include "ptpobjinfoparser.h"
#define DEV_ADDR 1
//Example -> Canon PowerShot S3 IS
#define DATA_IN_EP 1
#define DATA_OUT_EP 2
#define INTERRUPT_EP 3
#define CONFIG_NUM 1
#define MAX_USB_STRING_LEN 64
/****** OSD INCLUDES ******/
#include "ArduCam_Max7456.h"
#include "OSD_Vars.h"
#define SerPri Serial.print
#define SerPriln Serial.println
#define SerAva Serial.available
#define SerRea Serial.read
void setup();
void loop();
FastSerialPort0(Serial);
/****** CAMSTATES CLASS ******/
class CamStateHandlers : public PSStateHandlers
{
bool stateConnected;
public:
CamStateHandlers() : stateConnected(false) {};
virtual void OnDeviceDisconnectedState(PTP *ptp);
virtual void OnDeviceInitializedState(PTP *ptp);
} CamStates;
/****** END CAMSTATES ******/
/****** OBJECTS ******/
OSD osd; //OSD object instance
CanonPS Ps(DEV_ADDR, DATA_IN_EP, DATA_OUT_EP, INTERRUPT_EP, CONFIG_NUM, &CamStates); //Canon PS object instance
SimpleTimer displayTimer, cameraTimer; //Timers
/********** HANDLERS**********/
void CamStateHandlers::OnDeviceDisconnectedState(PTP *ptp)
{
if (stateConnected)
{
cameraTimer.Disable();
stateConnected = false;
Notify(PSTR("Camera disconnected\r\n"));
}
}
void CamStateHandlers::OnDeviceInitializedState(PTP *ptp)
{
if (!stateConnected)
{
Notify(PSTR("Camera connected\r\n"));
stateConnected = true;
cameraTimer.Enable();
}
}
/**********END TIMERS HANDLERS******/
//Demo vars control (!!! Remember to delete it after APM integration)
float lastGPSUpdate = 0;
float lastBatUpdate = 0;
float lastHeadUpdate = 0;
float headIncrementSignal = 1;
void setup()
{
Serial.begin(57600);
pinMode(10, OUTPUT); //usb host CS
pinMode(6, OUTPUT); //OSD CS
unplugSlaves();
osd.init();
startPanels();
delay( 200 );
unplugSlaves();
Ps.Setup();
delay( 2000 );
osd.clear();
//Setting Timers
displayTimer.Set(&OnDisplayTimer, 150);
cameraTimer.Set(&OnCameraTimer, 500);
delay( 200 );
displayTimer.Enable(); //Starting OSD timer (camera timer depends on camera is attached or not)
}
void loop(){
unplugSlaves();
displayTimer.Run();
unplugSlaves();
Ps.Task();
cameraTimer.Run();
}
void OnCameraTimer()
{
readSerialCommand();
}
void OnDisplayTimer()
{
osd_job();
}
void writeOSD() //Interrupt function (ISR)
{
//Serial.println("Interrupt!");
detachInterrupt(0); //It will respect the new aquisition
unplugSlaves();
writePanels();//Check OSD_Panels Tab!
}
void osd_job()
{
/*Its the place for data aquisition*/
/*JUST Simulated here as DEMO and test*/
if(millis() > lastGPSUpdate + 100){
lastGPSUpdate = millis();
lat+=0.0001;
lon+=0.002;
hom_dis+=1;
}
if(millis() > lastHeadUpdate + 100){
lastHeadUpdate = millis();
//looping forever
if(head >= 180){
head -= 360;
}else head+=5;
//or ping-pong
/*if(head >= 180) headIncrementSignal = -1;
if(head <= -180) headIncrementSignal = 1;
head += 1.8 * headIncrementSignal;*/
}
if(millis() > lastBatUpdate + 2000){
lastBatUpdate = millis();
alt++;
vel+=5;
bat_val -= 0.1;
}
//Next line will arm OSD function for the next VSync interruption
attachInterrupt(0, writeOSD, FALLING);
}
void readSerialCommand() {
char queryType;
if (SerAva()) {
queryType = SerRea();
switch (queryType) {
case 'A': //Activate Capture
Ps.Initialize(true);
//mapping capture target to SD card
Ps.SetDevicePropValue(PS_DPC_CaptureTransferMode, (uint16_t)0x0F);
break;
case 'C': //Capture!!!
Ps.Capture();
break;
case 'D': //Deactivate Capture
Ps.Operation(PS_OC_ViewfinderOff);
Ps.Initialize(false);
break;
case 'L': //Focus Lock
Ps.Operation(PS_OC_FocusLock);
delay(50);
break;
case 'O': //ViewFinder Output. 1 = LCD. 2 = AV.
Ps.SetDevicePropValue(PS_DPC_CameraOutput, (uint16_t)readFloatSerial());
break;
case 'U': //Focus Unlock
Ps.Operation(PS_OC_FocusUnlock);
break;
case 'V': //ViewFinder ON/OFF
if((uint16_t)readFloatSerial() == 0){
Ps.Operation(PS_OC_ViewfinderOff);
}
else Ps.Operation(PS_OC_ViewfinderOn);
break;
case 'X': //Close session forever
Ps.Initialize(false);
break;
case 'Z': //Set Zoom
Ps.SetDevicePropValue(PS_DPC_Zoom, (uint16_t)readFloatSerial());
break;
}
}
}
float readFloatSerial() {
byte index = 0;
byte timeout = 0;
char data[128] = "";
do {
if (SerAva() == 0) {
delay(10);
timeout++;
}
else {
data[index] = SerRea();
timeout = 0;
index++;
}
}
while ((data[constrain(index-1, 0, 128)] != ';') && (timeout < 5) && (index < 128));
return atof(data);
}
void unplugSlaves(){
digitalWrite(10, HIGH); //unplug USB Host
digitalWrite(6, HIGH); //unplug OSD
}