Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 1701 → Rev 1702

/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/EOSCamController.pde
0,0 → 1,556
/* Digital camera controller board test sketch */
//#include <Spi.h>
#include <Max3421e.h>
#include <Usb.h>
#include <Max_LCD.h>
#include <simpletimer.h>
#include <valuelist.h>
#include <canoneos.h>
#include <qep_port.h>
 
#include "camcontroller.h"
#include "controls.h"
#include "eoseventparser.h"
#include "dataitem.h"
#include "screenitem.h"
#include "screen.h"
#include "menu.h"
#include "hdrcapture.h"
 
#define DEV_ADDR 1
 
// Canon EOS 400D
#define DATA_IN_EP 1
#define DATA_OUT_EP 2
#define INTERRUPT_EP 3
#define CONFIG_NUM 1
 
#define EEP_APERTURE_LIST_OFFSET 0
#define EEP_APERTURE_LIST_SIZE 32
 
#define EEP_SHTSPEED_LIST_OFFSET (EEP_APERTURE_LIST_OFFSET + EEP_APERTURE_LIST_SIZE)
#define EEP_SHTSPEED_LIST_SIZE 64
 
#define EEP_WBALANCE_LIST_OFFSET (EEP_SHTSPEED_LIST_OFFSET + EEP_SHTSPEED_LIST_SIZE)
#define EEP_WBALANCE_LIST_SIZE 12
 
#define EEP_PICSTYLE_LIST_OFFSET (EEP_WBALANCE_LIST_OFFSET + EEP_WBALANCE_LIST_SIZE)
#define EEP_PICSTYLE_LIST_SIZE 12
 
#define EEP_EXPOCOR_LIST_OFFSET (EEP_PICSTYLE_LIST_OFFSET + EEP_PICSTYLE_LIST_SIZE)
#define EEP_EXPOCOR_LIST_SIZE 48
 
#define EEP_ISO_LIST_OFFSET (EEP_EXPOCOR_LIST_OFFSET + EEP_EXPOCOR_LIST_SIZE)
#define EEP_ISO_LIST_SIZE 8
 
EEPROMByteList vlAperture(EEP_APERTURE_LIST_OFFSET, EEP_APERTURE_LIST_SIZE);
EEPROMByteList vlShutterSpeed(EEP_SHTSPEED_LIST_OFFSET, EEP_SHTSPEED_LIST_SIZE);
EEPROMByteList vlWhiteBalance(EEP_WBALANCE_LIST_OFFSET, EEP_WBALANCE_LIST_SIZE);
EEPROMByteList vlPictureStyle(EEP_PICSTYLE_LIST_OFFSET, EEP_PICSTYLE_LIST_SIZE);
EEPROMByteList vlIso(EEP_ISO_LIST_OFFSET, EEP_ISO_LIST_SIZE);
EEPROMByteList vlExpCompensation(EEP_EXPOCOR_LIST_OFFSET, EEP_EXPOCOR_LIST_SIZE);
 
class CamStateHandlers : public EOSStateHandlers
{
bool stateConnected;
public:
CamStateHandlers() : stateConnected(false) {};
virtual void OnDeviceDisconnectedState(PTP *ptp);
virtual void OnDeviceInitializedState(PTP *ptp);
};
 
class CamHDRCapture : public HDRCapture
{
public:
CamHDRCapture(CanonEOS &eos) : HDRCapture(eos) {};
protected:
virtual void OnFrameCaptured(uint16_t left);
virtual void OnSelfTimerProgress(uint32_t left);
virtual void OnIntrTimerProgress(uint32_t left);
};
 
CamStateHandlers CamStates;
Max_LCD LCD;
SimpleTimer ControlTimer, PTPPollTimer;
 
CanonEOS Eos(DEV_ADDR, DATA_IN_EP, DATA_OUT_EP, INTERRUPT_EP, CONFIG_NUM, &CamStates);
CamHDRCapture hdrCapture(Eos);
GPInRegister ExtControls(Eos.GetMax());
QEvent evtTick, evtAbort;
 
//--- (0) Message Screen ----------------------------------------------------------------------
PgmStringDataItem diFirst(msgCamera);
PgmStringDataItem diSecond(msgDisconnected);
 
ScreenItem siFirst (5, 0, 16, false, &diFirst);
ScreenItem siSecond (2, 1, 16, false, &diSecond);
 
ScreenItem *messageScreenItems[] PROGMEM = { &siFirst, &siSecond };
Screen messageScreen(2, (ScreenItem*)messageScreenItems);
 
//--- (1) Main Menu Screen --------------------------------------------------------------------
ScreenItem siIntervalometer (1, 0, 8, true, (const char*)&msgIntervalometer);
ScreenItem siSettings (1, 1, 8, false, (const char*)&msgSettings);
 
ScreenItem *mainMenuScreenItems[] PROGMEM = { &siIntervalometer, &siSettings };
Screen scrMainMenu(2, (ScreenItem*)mainMenuScreenItems);
 
//--- (2) Timer Menu Screen -------------------------------------------------------------------
ScreenItem siSelf (1, 0, 4, true, (const char*)&msgSetSelf);
ScreenItem siFrames (1, 1, 4, false, (const char*)&msgSetFrames);
ScreenItem siBkt (6, 0, 3, false, (const char*)&msgSetBkt);
ScreenItem siInterval (6, 1, 3, false, (const char*)&msgSetInterval);
ScreenItem siRun (10, 0, 4, false, (const char*)&msgSetRun);
ScreenItem siExit (10, 1, 4, false, (const char*)&msgExit);
 
ScreenItem *timerSettingsScreenItems[] PROGMEM = { &siSelf, &siFrames, &siBkt, &siInterval, &siRun, &siExit };
Screen timerSettingsScreen(6, (ScreenItem*)timerSettingsScreenItems);
 
//--- (3) Self Timer Screen -------------------------------------------------------------------
DIT_TIMER_DIGIT_PAIR diHourSelf(0), diHourInt(0),
diMinSelf(0), diMinInt(0),
diSecSelf(0), diSecInt(0);
 
ScreenItem siSelfTimer(0, 0, 16, false, (const char*)&msgSelfTimer);
ScreenItem siHourSelf(3, 1, 2, false, &diHourSelf);
ScreenItem siMinSelf (6, 1, 2, false, &diMinSelf);
ScreenItem siSecSelf (9, 1, 2, false, &diSecSelf);
 
ScreenItem *scitmSelfTimerSet[] PROGMEM = { &siSelfTimer, &siHourSelf, &siMinSelf, &siSecSelf };
Screen scrSelfTimerSet(4, (ScreenItem*)scitmSelfTimerSet);
 
//--- (4) Number of Frames Screen -------------------------------------------------------------
IntDataItem<uint16_t, 5> diFramesCount(0);
IntDataItem<uint16_t, 5> diFramesLeft(0);
 
ScreenItem siFramesText (5, 0, 6, false, (const char*)&msgCntFrames);
ScreenItem siFramesCount (6, 1, 4, false, &diFramesCount);
 
ScreenItem *scitmFramesSet[] PROGMEM = { &siFramesText, &siFramesCount };
Screen scrFramesSet(2, (ScreenItem*)scitmFramesSet);
 
//--- (5) Bracketing Screen -------------------------------------------------------------------
KeyValuePairDataItem<uint8_t, 37, 7> diBktEV(0, ExpCompTitles);
KeyValuePairDataItem<uint8_t, 37, 7> diBktStep(0, ExpCompTitles);
uint8_t nBktStep;
uint8_t nBktNegativeIndex;
uint8_t nBktPositiveIndex;
 
ScreenItem siBracketing(0, 0, 15, false, (const char*)&msgBracketing);
ScreenItem siBktEV (1, 1, 6, false, &diBktEV);
ScreenItem siBktStep (9, 1, 6, false, &diBktStep);
 
ScreenItem *scitmBkt[] PROGMEM = { &siBracketing, &siBktEV, &siBktStep };
Screen scrBktSet(3, (ScreenItem*)scitmBkt);
 
//--- (6) Interval Timer Screen ---------------------------------------------------------------
ScreenItem siIntTimer(0, 0, 16, false, (const char*)&msgIntTimer);
ScreenItem siHourInt(3, 1, 2, false, &diHourInt);
ScreenItem siMinInt (6, 1, 2, false, &diMinInt);
ScreenItem siSecInt (9, 1, 2, false, &diSecInt);
 
ScreenItem *scitmIntTimerSet[] PROGMEM = { &siIntTimer, &siHourInt, &siMinInt, &siSecInt };
Screen scrIntTimerSet(4, (ScreenItem*)scitmIntTimerSet);
 
//--- (7) Run Screen ---------------------------------------------------------------------------
TimeSpanDataItem diLeftTimer(0);
TimeSpanDataItem diIntTimer(0);
 
ScreenItem siRunLeftTime( 0, 0, 8, false, &diLeftTimer);
ScreenItem siRunIntTime( 0, 1, 8, false, &diIntTimer);
ScreenItem siRunFramesLeft ( 10, 0, 4, false, &diFramesLeft);
ScreenItem siAbort(10, 1, 5, false, (const char*)&msgAbort);
 
ScreenItem *scitmRun[] PROGMEM = { &siRunLeftTime, &siRunIntTime, &siRunFramesLeft, &siAbort };
Screen scrRun(4, (ScreenItem*)scitmRun);
 
//--- (8) Camera Settings Screen ---------------------------------------------------------------
DIT_MODE diMode(0, ModeTitles);
DIT_APERTURE diAperture(0, ApertureTitles);
DIT_WB diWb(0, WbTitles);
DIT_SHUTTER_SPEED diShutterSpeed(0, ShutterSpeedTitles);
DIT_PSTYLE diPStyle(0, PStyleTitles);
DIT_ISO diIso(0, IsoTitles);
DIT_EXPCOMP diExpComp(0, ExpCompTitles);
 
ScreenItem siMode ( 0, 0, 3, false, &diMode);
ScreenItem siAperture ( 0, 1, 3, false, &diAperture);
ScreenItem siWb ( 4, 0, 3, false, &diWb);
ScreenItem siShutterSpeed( 4, 1, 4, false, &diShutterSpeed);
ScreenItem siPStyle ( 8, 0, 3, false, &diPStyle);
ScreenItem siIso (12, 0, 4, false, &diIso);
ScreenItem siExpComp ( 9, 1, 6, false, &diExpComp);
 
ScreenItem *scitmSettings[] PROGMEM = { &siMode, &siAperture, &siWb, &siShutterSpeed, &siPStyle, &siIso, &siExpComp };
Screen scrSettings(7, (ScreenItem*)scitmSettings);
 
IntSpin<DIT_TIMER_DIGIT_PAIR, uint8_t> hourSpinSelf(0, 99, 1, &diHourSelf, NULL);
IntSpin<DIT_TIMER_DIGIT_PAIR, uint8_t> minSpinSelf(0, 99, 1, &diMinSelf, NULL);
IntSpin<DIT_TIMER_DIGIT_PAIR, uint8_t> secSpinSelf(0, 99, 1, &diSecSelf, NULL);
 
IntSpin<DIT_TIMER_DIGIT_PAIR, uint8_t> hourSpinInt(0, 99, 1, &diHourInt, NULL);
IntSpin<DIT_TIMER_DIGIT_PAIR, uint8_t> minSpinInt(0, 99, 1, &diMinInt, NULL);
IntSpin<DIT_TIMER_DIGIT_PAIR, uint8_t> secSpinInt(0, 99, 1, &diSecInt, NULL);
 
 
void SpinSetAperture(DataItemBase *data_item)
{
Eos.SetProperty(EOS_DPC_Aperture, ((DIT_APERTURE*)data_item)->Get());
};
 
void SpinSetShutterSpeed(DataItemBase *data_item)
{
Eos.SetProperty(EOS_DPC_ShutterSpeed, ((DIT_SHUTTER_SPEED*)data_item)->Get());
};
 
void SpinSetWb(DataItemBase *data_item)
{
Eos.SetProperty(EOS_DPC_WhiteBalance, ((DIT_WB*)data_item)->Get());
};
 
void SpinSetPStyle(DataItemBase *data_item)
{
Eos.SetProperty(EOS_DPC_PictureStyle, ((DIT_PSTYLE*)data_item)->Get());
};
 
void SpinSetIso(DataItemBase *data_item)
{
Eos.SetProperty(EOS_DPC_Iso, ((DIT_ISO*)data_item)->Get());
};
 
void SpinSetExpComp(DataItemBase *data_item)
{
Eos.SetProperty(EOS_DPC_ExposureCompensation, ((DIT_EXPCOMP*)data_item)->Get());
};
 
void SpinUpdateBktStepValues(DataItemBase *data_item);
void SpinUpdateBktStep(DataItemBase *data_item);
 
EEPROMListIntSpin<DIT_APERTURE, VT_APERTURE> spinAperture(&vlAperture, &diAperture, &SpinSetAperture);
EEPROMListIntSpin<DIT_SHUTTER_SPEED, VT_SHSPEED> spinShutterSpeed(&vlShutterSpeed, &diShutterSpeed, &SpinSetShutterSpeed);
EEPROMListIntSpin<DIT_WB, VT_WB> spinWb(&vlWhiteBalance, &diWb, &SpinSetWb);
EEPROMListIntSpin<DIT_PSTYLE, VT_PSTYLE> spinPStyle(&vlPictureStyle, &diPStyle, &SpinSetPStyle);
EEPROMListIntSpin<DIT_ISO, VT_ISO> spinIso(&vlIso, &diIso, &SpinSetIso);
 
EEPROMListIntSpin<EXP_COMP_DATA_ITEM, VT_EXPCOMP> spinExpComp(&vlExpCompensation, &diExpComp, &SpinSetExpComp);
EEPROMListIntSpin<EXP_COMP_DATA_ITEM, VT_EXPCOMP> spinBktEV (&vlExpCompensation, &diBktEV, &SpinUpdateBktStepValues);
 
BKT_STEP_VALUE_LIST vlExpCompStep;
 
SRAMListIntSpin<EXP_COMP_DATA_ITEM, VT_EXPCOMP, BKT_STEP_VALUE_LIST> spinBktStep(&vlExpCompStep, &diBktStep, &SpinUpdateBktStep);
 
 
void SpinUpdateBktStepValues(DataItemBase *data_item)
{
uint8_t cur_value = ((EXP_COMP_DATA_ITEM*)data_item)->Get();
vlExpCompStep.SetSize(0);
// Check value for zerro. Exit on zerro.
if (cur_value == 0)
return;
// Calculate negative and positive values of expo compensation
uint8_t negative_value = (cur_value & 0x80) ? cur_value : ~(cur_value - 1);
uint8_t positive_value = (cur_value & 0x80) ? ~(cur_value - 1) : cur_value;
// Get indices of negative and positive expo compensation values
uint16_t negative_index = vlExpCompensation.GetValueIndex(negative_value);
uint16_t positive_index = vlExpCompensation.GetValueIndex(positive_value);
 
nBktNegativeIndex = negative_index;
nBktPositiveIndex = positive_index;
// Calculate interval length
uint16_t len = positive_index - negative_index;
 
// Calculate zerro value index
uint16_t zerro_index = vlExpCompensation.GetValueIndex(0);
 
// Calculate positive index offset
uint16_t zerro_based_offset = positive_index - zerro_index;
// Calculate all possible interval indices
for (uint16_t i = zerro_based_offset, j = positive_index; i>0; i--, j--)
{
// Insert values into the list
if (len % i == 0)
vlExpCompStep.Append(vlExpCompensation.Get(j));
}
diBktStep.Set(cur_value);
diBktStep.SetUpdated(true);
};
 
void SpinUpdateBktStep(DataItemBase *data_item)
{
uint8_t cur_value = ((EXP_COMP_DATA_ITEM*)data_item)->Get();
nBktStep = vlExpCompensation.GetValueIndex(cur_value) - vlExpCompensation.GetValueIndex(0);
};
 
void MenuExit();
void MenuSetAperture();
void MenuSetShutterSpeed();
void MenuSetWb();
void MenuSetPStyle();
void MenuSetIso();
void MenuSetExpComp();
 
extern Menu mainMenu;
 
//--- Camera Settings Menu -----------------------------------------------------------------
MenuItem settingsMenuItems[] = { {&siMode, &MenuExit}, {&siAperture, &MenuSetAperture}, {&siWb, &MenuSetWb}, {&siShutterSpeed, &MenuSetShutterSpeed}, {&siPStyle, &MenuSetPStyle}, {&siIso, &MenuSetIso}, {&siExpComp, &MenuSetExpComp} };
Menu settingsMenu(8, 7, settingsMenuItems, 0, &mainMenu);
 
void MenuSetAperture() { spinAperture.SetReturnState(&settingsMenu); StateMachine::SetState(&spinAperture); };
void MenuSetShutterSpeed() { spinShutterSpeed.SetReturnState(&settingsMenu); StateMachine::SetState(&spinShutterSpeed); };
void MenuSetWb(){ spinWb.SetReturnState(&settingsMenu); StateMachine::SetState(&spinWb); };
void MenuSetPStyle(){ spinPStyle.SetReturnState(&settingsMenu); StateMachine::SetState(&spinPStyle); };
void MenuSetIso(){ spinIso.SetReturnState(&settingsMenu); StateMachine::SetState(&spinIso); };
void MenuSetExpComp(){ spinExpComp.SetReturnState(&mainMenu); StateMachine::SetState(&spinExpComp); };
 
//--- Self Timer Menu ----------------------------------------------------------------------
void MenuSelfSetH();
void MenuSelfSetM();
void MenuSelfSetS();
 
extern Menu timerSettingsMenu;
 
MenuItem selfSetMenuItems[] = { {&siHourSelf, &MenuSelfSetH}, {&siMinSelf, &MenuSelfSetM}, {&siSecSelf, &MenuSelfSetS} };
Menu selfSetMenu(3, 3, selfSetMenuItems, 0, &timerSettingsMenu);
 
void MenuSelfSetH() { hourSpinSelf.SetReturnState(&selfSetMenu); StateMachine::SetState(&hourSpinSelf); };
void MenuSelfSetM() { minSpinSelf.SetReturnState(&selfSetMenu); StateMachine::SetState(&minSpinSelf); };
 
//--- Timer Settings Menu ------------------------------------------------------------------
void MenuSelf();
void MenuBkt();
void MenuFrames();
void MenuInterval();
void MenuExit();
void MenuRun();
 
MenuItem timerSettingsMenuItems[] = { {&siSelf, &MenuSelf}, {&siFrames, &MenuFrames}, {&siBkt, &MenuBkt}, {&siInterval, &MenuInterval}, {&siRun, &MenuRun}, {&siExit, &MenuExit} };
Menu timerSettingsMenu(2, 6, timerSettingsMenuItems, 0, &mainMenu);
 
void MenuSelfSetS() { secSpinSelf.SetReturnState(&timerSettingsMenu); StateMachine::SetState(&secSpinSelf); };
 
void MenuSelf() { StateMachine::SetState(&selfSetMenu); };
 
void MenuBktSetStep();
void MenuBktStepExit();
 
MenuItem bktSetMenuItems[] = { {&siBktEV, &MenuBktSetStep}, {&siBktStep, &MenuBktStepExit} };
Menu bktSetMenu(5, 2, bktSetMenuItems, 0, &timerSettingsMenu);
 
void MenuBktSetStep()
{
spinBktEV.SetReturnState(&bktSetMenu);
 
if (vlExpCompensation.GetSize())
StateMachine::SetState(&spinBktEV);
};
 
void MenuBktStepExit()
{
spinBktStep.SetReturnState(&timerSettingsMenu);
 
if (vlExpCompensation.GetSize())
StateMachine::SetState(&spinBktStep);
};
 
void MenuBkt()
{
if (vlExpCompensation.GetSize())
StateMachine::SetState(&bktSetMenu);
};
 
 
IntSpin<IntDataItem<uint16_t, 5>, int16_t> framesSpin(0, 9999, 1, &diFramesCount, NULL);
 
void MenuFrames() { framesSpin.SetReturnState(&timerSettingsMenu); Screen::Set(4); StateMachine::SetState(&framesSpin); };
 
void MenuIntSetH();
void MenuIntSetM();
void MenuIntSetS();
 
MenuItem intSetMenuItems[] = { {&siHourInt, &MenuIntSetH}, {&siMinInt, &MenuIntSetM}, {&siSecInt, &MenuIntSetS} };
Menu intSetMenu(6, 3, intSetMenuItems, 0, &timerSettingsMenu);
 
void MenuIntSetH() { hourSpinInt.SetReturnState(&intSetMenu); StateMachine::SetState(&hourSpinInt); };
void MenuIntSetM() { minSpinInt.SetReturnState(&intSetMenu); StateMachine::SetState(&minSpinInt); };
void MenuIntSetS() { secSpinInt.SetReturnState(&timerSettingsMenu); StateMachine::SetState(&secSpinInt); };
 
void MenuInterval() { StateMachine::SetState(&intSetMenu); };
 
void MenuRunAbort()
{
hdrCapture.PostEvent(&evtAbort);
diFramesLeft.Set(0);
StateMachine::SetState(&timerSettingsMenu);
};
 
MenuItem runMenuItems[] = { {&siAbort, &MenuRunAbort} };
Menu runMenu(7, 1, runMenuItems, 0);
 
void MenuRun()
{
if (!diFramesCount.Get())
return;
uint32_t intr_timeout = ((uint32_t)diHourInt.Get() * 3600 + (uint32_t)diMinInt.Get() * 60 + (uint32_t)diSecInt.Get());
uint32_t self_timeout = ((uint32_t)diHourSelf.Get() * 3600 + (uint32_t)diMinSelf.Get() * 60 + (uint32_t)diSecSelf.Get());
 
diFramesLeft.Set(diFramesCount.Get());
diLeftTimer.Set(self_timeout);
diIntTimer.Set(intr_timeout);
 
SetEvt setEvt;
setEvt.sig = SET_FRAMES_SIG;
setEvt.value = diFramesCount.Get();
hdrCapture.dispatch(&setEvt);
setEvt.sig = SET_FRAME_TIMEOUT_SIG;
setEvt.value = intr_timeout;
hdrCapture.dispatch(&setEvt);
setEvt.sig = SET_SELF_TIMEOUT_SIG;
setEvt.value = self_timeout;
hdrCapture.dispatch(&setEvt);
SetBktEvt setBktEvt;
setBktEvt.sig = SET_BRACKETING_SIG;
setBktEvt.step = nBktStep;
setBktEvt.negative = nBktNegativeIndex;
setBktEvt.positive = nBktPositiveIndex;
hdrCapture.dispatch(&setBktEvt);
StateMachine::SetState(&runMenu);
setEvt.sig = RUN_SIG;
hdrCapture.dispatch(&setEvt);
};
 
//--- Main Menu ----------------------------------------------------------------------------
void MenuIntervalometer() { StateMachine::SetState(&timerSettingsMenu); };
 
void MenuSettings()
{
StateMachine::SetState(&settingsMenu);
};
 
MenuItem mainMenuItems[] = { {&siIntervalometer, &MenuIntervalometer}, {&siSettings, &MenuSettings} };
Menu mainMenu(1, 2, mainMenuItems, 0);
 
void MenuExit() { StateMachine::SetState(&mainMenu); };
 
class DummyMenu : public StateMachine
{
public:
virtual bool OnInitialState()
{
Screen::Set(0);
return true;
};
} DisconnectedState;
 
void CamStateHandlers::OnDeviceDisconnectedState(PTP *ptp)
{
if (stateConnected)
{
stateConnected = false;
PTPPollTimer.Disable();
StateMachine::SetState(&DisconnectedState);
}
}
 
void CamStateHandlers::OnDeviceInitializedState(PTP *ptp)
{
if (!stateConnected)
{
stateConnected = true;
PTPPollTimer.Enable();
StateMachine::SetState(&mainMenu);
}
hdrCapture.Run();
}
 
void CamHDRCapture::OnFrameCaptured(uint16_t left)
{
diFramesLeft.Set(left);
 
if (!left)
StateMachine::SetState(&timerSettingsMenu);
}
 
void CamHDRCapture::OnSelfTimerProgress(uint32_t left)
{
diLeftTimer.Set(left);
}
 
void CamHDRCapture::OnIntrTimerProgress(uint32_t left)
{
diIntTimer.Set(left);
}
 
void OnControlTimer()
{
ExtControls.CheckControls();
hdrCapture.PostEvent(&evtTick);
Screen::Run(&LCD);
}
 
void OnPTPPollTimer()
{
EOSEventParser prs;
Eos.EventCheck(&prs);
diLeftTimer.SetUpdated(true);
diIntTimer.SetUpdated(true);
}
 
void setup()
{
StateMachine::SetState(&DisconnectedState);
#ifdef PTPDEBUG
Serial.begin(115200);
#endif
 
Eos.Setup();
delay( 200 );
// set up the LCD's number of rows and columns:
LCD.begin(16, 2);
LCD.clear();
LCD.home();
LCD.setCursor(0,0);
PTPPollTimer.Set(OnPTPPollTimer, 300);
// 1ms is the perfect interval for encoder polling
ControlTimer.Set(OnControlTimer, 1);
ControlTimer.Enable();
evtTick.sig = TICK_MILLIS_SIG;
evtAbort.sig = ABORT_SIG;
hdrCapture.init();
 
#ifdef PTPDEBUG
Serial.println("Start");
#endif
}
 
void loop()
{
Eos.Task();
PTPPollTimer.Run();
ControlTimer.Run();
}
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/camcontroller.h
0,0 → 1,49
/* Camera controller header */
#ifndef __CAMCONTROLLER_H__
#define __CAMCONTROLLER_H__
 
#include <inttypes.h>
#include <avr/pgmspace.h>
 
#include <canoneos.h>
#include <eosvaluetitles.h>
#include "menu.h"
 
const char msgSetSelf[] PROGMEM = "SELF";
const char msgSetFrames[] PROGMEM = "FRMS";
const char msgSetBkt[] PROGMEM = "BKT";
const char msgSetInterval[] PROGMEM = "INT";
const char msgExit[] PROGMEM = "EXIT";
const char msgSetRun[] PROGMEM = "RUN ";
const char msgAbort[] PROGMEM = "ABORT";
const char msgLeft[] PROGMEM = "LEFT";
 
const char msgError[] PROGMEM = "ERROR:";
const char msgCamera[] PROGMEM = "CAMERA";
const char msgDisconnected[] PROGMEM = "DISCONNECTED";
 
const char msgSelfTimer[] PROGMEM = "SELF TIMER h/m/s";
const char msgBracketing[] PROGMEM = "BKT(RANGE/STEP)";
const char msgSteps[] PROGMEM = "steps";
const char msgCntFrames[] PROGMEM = "FRAMES";
const char msgIntTimer[] PROGMEM = "INT TIMER h/m/s";
const char msgIntervalometer[] PROGMEM = "INTERVAL";
const char msgSettings[] PROGMEM = "SETTINGS";
const char msgClock[] PROGMEM = "CLOCK";
const char msgEV[] PROGMEM = "EV";
 
typedef KeyValuePairDataItem<VT_EXPCOMP, VT_EXPCOMP_COUNT, VT_EXPCOMP_TEXT_LEN> EXP_COMP_DATA_ITEM; // Exposure compensation data item type
typedef SRAMValueList<VT_EXPCOMP, 16> BKT_STEP_VALUE_LIST; // Bracketing step value list type
 
//--- Data Item Types ---------------------------------------------------------
typedef KeyValuePairDataItem<VT_MODE, VT_MODE_COUNT, VT_MODE_TEXT_LEN> DIT_MODE;
typedef KeyValuePairDataItem<VT_APERTURE, VT_APT_COUNT, VT_APT_TEXT_LEN> DIT_APERTURE;
typedef KeyValuePairDataItem<VT_WB, VT_WB_COUNT, VT_WB_TEXT_LEN> DIT_WB;
typedef KeyValuePairDataItem<VT_SHSPEED, VT_SHSPEED_COUNT, VT_SHSPEED_TEXT_LEN> DIT_SHUTTER_SPEED;
typedef KeyValuePairDataItem<VT_PSTYLE, VT_PSTYLE_COUNT, VT_PSTYLE_TEXT_LEN> DIT_PSTYLE;
typedef KeyValuePairDataItem<VT_ISO, VT_ISO_COUNT, VT_ISO_TEXT_LEN> DIT_ISO;
typedef KeyValuePairDataItem<VT_EXPCOMP, VT_EXPCOMP_COUNT, VT_EXPCOMP_TEXT_LEN> DIT_EXPCOMP;
typedef IntDataItem<uint8_t, 3> DIT_TIMER_DIGIT_PAIR;
 
 
#endif //__CAMCONTROLLER_H__
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/controls.cpp
0,0 → 1,50
#include <Max3421e.h>
#include "controls.h"
 
StateMachine* StateMachine::currentState = NULL;
 
void GPInRegister::CheckControls()
{
int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
ControlStates previous = controlStates;
controlStates = (pMax->gpioRd() & (GPIN_ENCODER_MASK | GPIN_ENC_BUT_MASK | GPIN_EXT_BUT_MASK));
ControlStates changes = (previous ^ controlStates);
if (previous == controlStates)
return;
ControlEvents *state_machine = (ControlEvents*)StateMachine::GetState();
if ((changes & GPIN_ENCODER_MASK))
{
uint8_t encoder = (previous & GPIN_ENCODER_MASK);
encoder <<= 2;
encoder |= (controlStates & GPIN_ENCODER_MASK);
encoderValue += enc_states[(encoder & 0x0f)];
if (encoderValue > 3 || encoderValue < -3)
{
if (state_machine)
state_machine->OnEncoderChanged(encoderValue >> 2);
encoderValue = 0;
}
}
if (!state_machine)
return;
if ((changes & GPIN_ENC_BUT_MASK))
{
if ((controlStates & GPIN_ENC_BUT_MASK))
state_machine->OnEncButtonUp();
else
state_machine->OnEncButtonDown();
}
if ((changes & GPIN_EXT_BUT_MASK))
{
if ((controlStates & GPIN_EXT_BUT_MASK))
state_machine->OnExtButtonUp();
else
state_machine->OnExtButtonDown();
}
}
 
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/controls.h
0,0 → 1,50
#ifndef __CONTROLS_H__
#define __CONTROLS_H__
 
#include <inttypes.h>
#include <avr/pgmspace.h>
 
class StateMachine
{
static StateMachine *currentState;
protected:
virtual bool OnInitialState() { return true; };
 
public:
static void SetState(StateMachine *state) { currentState = state; currentState->OnInitialState(); };
static StateMachine* GetState() { return StateMachine::currentState; };
};
 
class ControlEvents : public StateMachine
{
public:
virtual bool OnEncoderChanged(int8_t value) { return true; };
virtual bool OnEncButtonUp() { return true; };
virtual bool OnEncButtonDown() { return true; };
virtual bool OnExtButtonUp() { return true; };
virtual bool OnExtButtonDown() { return true; };
};
 
#define GPIN_ENCODER_MASK 0x03
#define GPIN_ENC_BUT_MASK 0x08
#define GPIN_EXT_BUT_MASK 0x10
 
#define GPIN_ENC_BUT_MASK 0x04
#define GPIN_EXT_BUT_MASK 0x08
 
 
typedef uint8_t ControlStates;
 
class GPInRegister
{
ControlStates controlStates;
MAX3421E *pMax;
int8_t encoderValue;
public:
GPInRegister(MAX3421E *pmax) : controlStates(GPIN_ENCODER_MASK | GPIN_ENC_BUT_MASK | GPIN_EXT_BUT_MASK), pMax(pMax), encoderValue(0) {};
void CheckControls();
};
 
#endif // __CONTROLS_H__
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/dataitem.cpp
0,0 → 1,51
#include "dataitem.h"
 
char TimeSpanDataItem::textValue[9] = "";
char TimerDataItem::textValue[9] = "";
 
char* itoa2(int val, uint8_t buf_size, char *buf, int8_t base, char c)
{
char sign = (val < 0) ? '-' : c;
buf[buf_size-1] = 0;
 
int8_t i = buf_size-2;
for(; val && i ; --i, val /= base)
buf[i] = "0123456789abcdef"[(val < 0) ? -(val % base) : val % base];
for (; i > 0; i--)
buf[i] = c;
buf[0] = sign;
return buf;
}
 
char* itoa2(uint8_t val, uint8_t buf_size, char *buf, int8_t base, char c)
{
buf[buf_size-1] = 0;
 
int8_t i = buf_size-2;
for(; val && i>=0 ; --i, val /= base)
buf[i] = "0123456789abcdef"[(val < 0) ? -(val % base) : val % base];
for (; i >= 0; i--)
buf[i] = c;
return buf;
}
 
char* itoa2(uint16_t val, uint8_t buf_size, char *buf, int8_t base, char c)
{
buf[buf_size-1] = 0;
 
int8_t i = buf_size-2;
for(; val && i>=0 ; --i, val /= base)
buf[i] = "0123456789abcdef"[val % base];
for (; i >= 0; i--)
buf[i] = c;
return buf;
}
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/dataitem.h
0,0 → 1,194
#if !defined(__DATAITEM_H__)
#define __DATAITEM_H__
 
#include <inttypes.h>
#include <canoneos.h>
#include <SimpleTimer.h>
#include <valuelist.h>
 
#define MUL10( a ) (((a) << 3 ) + ((a) << 1 ))
 
char* itoa2(int val, uint8_t buf_size, char *buf, int8_t base, char c);
char* itoa2(uint8_t val, uint8_t buf_size, char *buf, int8_t base, char c);
char* itoa2(uint16_t val, uint8_t buf_size, char *buf, int8_t base, char c);
 
class DataItemBase
{
protected:
bool isUpdated;
public:
virtual void GetText(char** str, bool &is_pgm) = 0;
bool IsUpdated() { return isUpdated; };
void SetUpdated(bool upd) { isUpdated = upd; };
};
 
class TimeSpanDataItem : public DataItemBase
{
uint32_t dataValue;
static char textValue[9];
public:
TimeSpanDataItem(uint32_t s) : dataValue(s) {};
 
virtual void GetText(char** str, bool &is_pgm)
{
{
uint16_t h = dataValue / 3600;
itoa2((uint16_t) h, 3, (char*)&textValue, 10, '0');
}
{
textValue[2] = ':';
uint16_t s = dataValue % 3600;
itoa2((uint16_t) s / 60, 3, (char*)(textValue+3), 10, '0');
textValue[5] = ':';
itoa2((uint16_t) s % 60, 3, (char*)(textValue+6), 10, '0');
}
*str = textValue;
is_pgm = false;
};
virtual void Set(uint32_t &val)
{
dataValue = val;
isUpdated = true;
};
};
 
#define MUL60( a ) (((a) << 6 ) - ((a) << 2 ))
#define MUL3600( a ) (((a) << 12 ) - ((a) << 9 ) + ((a) << 4 ))
 
class TimerDataItem : public DataItemBase
{
SimpleTimer &dataValue;
static char textValue[9];
public:
TimerDataItem(SimpleTimer &t) : dataValue(t) {};
 
virtual void GetText(char** str, bool &is_pgm)
{
uint16_t time_left = dataValue.TimeLeft() / 1000;
uint16_t ss = time_left % 60;
time_left /= 60;
uint16_t mm = time_left % 60;
time_left /= 60;
uint16_t hh = time_left;
itoa2((uint16_t)hh, 3, (char*)&textValue, 10, '0');
textValue[2] = ':';
itoa2((uint16_t)mm, 3, (char*)(textValue+3), 10, '0');
textValue[5] = ':';
itoa2((uint16_t)ss, 3, (char*)(textValue+6), 10, '0');
*str = textValue;
is_pgm = false;
};
};
 
template <class VALUE_TYPE, const uint8_t TABLE_SIZE, const uint8_t TEXT_SIZE>
class KeyValuePairDataItem : public DataItemBase
{
VALUE_TYPE dataValue;
const ValueTitle<VALUE_TYPE, TEXT_SIZE> *ptrTitles;
public:
KeyValuePairDataItem(VALUE_TYPE val, const ValueTitle<VALUE_TYPE, TEXT_SIZE> *p) : dataValue(val), ptrTitles(p)
{};
virtual void GetText(char** str, bool &is_pgm)
{
*str = (char*)FindTitle<VALUE_TYPE, TEXT_SIZE>(TABLE_SIZE, ptrTitles, dataValue);
is_pgm = true;
};
VALUE_TYPE Get() { return dataValue; };
void Set(VALUE_TYPE val) { dataValue = val; isUpdated = true; };
};
 
template <class VALUE_TYPE, const uint8_t TEXT_LEN>
class IntDataItem : public DataItemBase
{
VALUE_TYPE dataValue;
static char valString[TEXT_LEN];
public:
IntDataItem() : dataValue(0) { isUpdated = true; };
IntDataItem(VALUE_TYPE data) : dataValue(data) {};
virtual void Set(VALUE_TYPE data)
{
dataValue = data;
isUpdated = true;
};
VALUE_TYPE Get() { return dataValue; };
virtual void GetText(char** str, bool &is_pgm)
{
*str = itoa2(dataValue, TEXT_LEN, (char*)&valString, 10, '0');
is_pgm = false;
};
void operator ++(int val)
{
dataValue += val;
isUpdated = true;
};
void operator --(int val)
{
dataValue -= val;
isUpdated = true;
};
};
 
template <class VALUE_TYPE, const uint8_t TEXT_LEN>
char IntDataItem<VALUE_TYPE,TEXT_LEN>::valString[TEXT_LEN] = "";
 
class PgmStringDataItem : public DataItemBase
{
const char *pStr;
public:
PgmStringDataItem(const char *str) : pStr(str) { isUpdated = true; };
void SetText(const char *str) { pStr = str; isUpdated = true; };
virtual void GetText(char** str, bool &is_pgm)
{
*str = (char*)pStr;
is_pgm = true;
};
};
 
template <const uint8_t STRLEN>
class StringDataItem : public DataItemBase
{
char theString[STRLEN];
void CopyString(char *src, char *dst)
{
char *s = src, *d = dst;
for (uint8_t cnt = 0; *s && cnt < STRLEN-1; cnt++, s++, d++)
*d = *s;
*d = 0;
};
public:
StringDataItem() { theString[0] = 0; isUpdated = true; };
StringDataItem(char *str) { CopyString(str, &theString); isUpdated = true; };
 
void SetText(char *str) { CopyString(str, &theString); isUpdated = true; };
virtual void GetText(char** str, bool &is_pgm)
{
*str = &theString;
is_pgm = false;
};
};
 
 
#endif // __DATAITEM_H__
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/eoseventparser.cpp
0,0 → 1,191
#include "eoseventparser.h"
#include "dataitem.h"
#include "camcontroller.h"
 
extern DIT_MODE diMode;
extern DIT_APERTURE diAperture;
extern DIT_WB diWb;
extern DIT_SHUTTER_SPEED diShutterSpeed;
extern DIT_PSTYLE diPStyle;
extern DIT_ISO diIso;
extern DIT_EXPCOMP diExpComp;
 
extern EEPROMByteList vlAperture;
extern EEPROMByteList vlShutterSpeed;
extern EEPROMByteList vlWhiteBalance;
extern EEPROMByteList vlPictureStyle;
extern EEPROMByteList vlExpCompensation;
extern EEPROMByteList vlIso;
 
bool EOSEventParser::EventRecordParse(uint8_t **pp, uint16_t *pcntdn)
{
switch (nRecStage)
{
case 0:
// Retrieves the size of the event record
if (!valueParser.Parse(pp, pcntdn))
return false;
 
nRecSize = (uint16_t)varBuffer;
 
// calculates the number of event parameters ( size / 4 - 1 )
paramCountdown = (nRecSize >> 2) - 1;
paramCount = 1;
nRecSize -= 4;
nRecStage ++;
case 1:
for (; paramCountdown; paramCountdown--, paramCount++, nRecSize -= 4)
{
if (!valueParser.Parse(pp, pcntdn))
return false;
 
switch (paramCount)
{
// Event Code
case 1:
eosEvent.eventCode = (uint16_t)varBuffer;
break;
// Property Code
case 2:
// if (eosEvent.eventCode == EOS_EC_ObjectCreated)
// {
// }
eosEvent.propCode = (uint16_t)varBuffer;
break;
// C189 - Property Value, C18A - Enumerator Type
case 3:
eosEvent.propValue = varBuffer;
if (eosEvent.eventCode == EOS_EC_DevPropChanged)
{
switch (eosEvent.propCode)
{
case EOS_DPC_Aperture:
diAperture.Set(varBuffer);
break;
case EOS_DPC_ShutterSpeed:
diShutterSpeed.Set(varBuffer);
break;
case EOS_DPC_ShootingMode:
diMode.Set(varBuffer);
break;
case EOS_DPC_WhiteBalance:
diWb.Set(varBuffer);
break;
case EOS_DPC_PictureStyle:
diPStyle.Set(varBuffer);
break;
case EOS_DPC_Iso:
diIso.Set(varBuffer);
break;
case EOS_DPC_ExposureCompensation:
diExpComp.Set(varBuffer);
break;
};
}
break;
// C18A/enumType == 3 - Size of enumerator array
case 4:
if (eosEvent.eventCode == EOS_EC_DevPropValuesAccepted)
{
switch (eosEvent.propCode)
{
case EOS_DPC_Aperture:
vlAperture.SetSize((uint8_t)varBuffer);
break;
case EOS_DPC_ShutterSpeed:
vlShutterSpeed.SetSize((uint8_t)varBuffer);
break;
case EOS_DPC_WhiteBalance:
vlWhiteBalance.SetSize((uint8_t)varBuffer);
break;
case EOS_DPC_PictureStyle:
vlPictureStyle.SetSize((uint8_t)varBuffer);
break;
case EOS_DPC_Iso:
vlIso.SetSize((uint8_t)varBuffer);
break;
case EOS_DPC_ExposureCompensation:
vlExpCompensation.SetSize((uint8_t)varBuffer);
break;
};
}
break;
// C18A/enumType == 3 - Enumerator Values
default:
if (eosEvent.eventCode == EOS_EC_DevPropValuesAccepted)
{
switch (eosEvent.propCode)
{
case EOS_DPC_Aperture:
vlAperture.Set(paramCount-5, (uint8_t)varBuffer);
break;
case EOS_DPC_ShutterSpeed:
vlShutterSpeed.Set(paramCount-5, (uint8_t)varBuffer);
break;
case EOS_DPC_WhiteBalance:
vlWhiteBalance.Set(paramCount-5, (uint8_t)varBuffer);
break;
case EOS_DPC_PictureStyle:
vlPictureStyle.Set(paramCount-5, (uint8_t)varBuffer);
break;
case EOS_DPC_ExposureCompensation:
vlExpCompensation.Set(paramCount-5, (uint8_t)varBuffer);
break;
case EOS_DPC_Iso:
vlIso.Set(paramCount-5, (uint8_t)varBuffer);
break;
} // switch (eosEvent.propCode)
}
} // switch (paramCount)
} // for
nRecStage ++;
case 2:
if (nRecSize)
if (!byteSkipper.Skip(pp, pcntdn, nRecSize))
return false;
 
nRecSize = 0;
nRecStage = 0;
}
return true;
}
 
void EOSEventParser::InitEOSEventStruct()
{
eosEvent.eventCode = constInitialEventCode;
eosEvent.propCode = 0;
eosEvent.propValue = 0;
}
 
 
void EOSEventParser::Parse(const uint16_t len, const uint8_t *pbuf, const uint32_t &offset)
{
uint8_t *p = (uint8_t*) pbuf;
uint16_t cntdn = len;
 
switch (nStage)
{
case 0:
p += 12;
cntdn -= 12;
nStage ++;
case 1:
theBuffer.valueSize = 4;
valueParser.Initialize(&theBuffer);
InitEOSEventStruct();
nStage ++;
case 2:
while (1)
{
if (!EventRecordParse(&p, &cntdn))
return;
if (IsLastEventRecord())
break;
InitEOSEventStruct();
}
nStage = 0;
}
}
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/eoseventparser.h
0,0 → 1,75
#ifndef __EOSEVENTPARSER_H__
#define __EOSEVENTPARSER_H__
 
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <Max_LCD.h>
#include <ptpcallback.h>
#include <canoneos.h>
 
 
struct EOSParamValues
{
uint8_t upperValue;
uint8_t currentValue;
uint8_t lowerValue;
};
 
#define MAX_OBJ_IN_LIST 8
 
class EOSEventParser : public PTPReadParser
{
const uint16_t constInitialEventCode;
 
uint8_t paramsChanged;
 
struct EOSEvent
{
uint16_t eventCode;
uint16_t propCode;
uint32_t propValue;
};
 
uint8_t nStage;
uint8_t nRecStage;
uint16_t nRecSize;
MultiValueBuffer theBuffer;
uint32_t varBuffer;
EOSEvent eosEvent;
uint16_t paramCountdown;
uint16_t paramCount;
 
MultiByteValueParser valueParser;
ByteSkipper byteSkipper;
 
bool EventRecordParse(uint8_t **pp, uint16_t *pcntdn);
bool IsLastEventRecord() { return (eosEvent.eventCode == 0); };
void InitEOSEventStruct();
 
public:
EOSEventParser() :
constInitialEventCode(0xFFFF),
nStage(0),
nRecStage(0),
nRecSize(0),
varBuffer(0),
paramCountdown(0),
paramsChanged(0)
{
theBuffer.pValue = &varBuffer;
};
 
void Reset()
{
nStage = 0;
nRecStage = 0;
nRecSize = 0;
varBuffer = 0;
paramCountdown = 0;
paramsChanged = 0;
};
 
virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint32_t &offset);
};
 
#endif // __EOSEVENTPARSER_H__
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/expcomp_macro.h
0,0 → 1,3
extern EEPROMByteList vlExpCompensation;
 
#define EXP_COMP_VALUE(i)((uint32_t)vlExpCompensation.Get((i)))
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/hdrcapture.cpp
0,0 → 1,336
#include "hdrcapture.h"
#include "expcomp_macro.h"
 
/* fixes avr-gcc incompatibility with virtual destructors */
void operator delete( void *p ) {}
 
QState HDRCapture::Initial(HDRCapture *me, QEvent const *e)
{
return Q_TRAN(&HDRCapture::Inactive);
}
 
QState HDRCapture::Inactive(HDRCapture *me, QEvent const *e)
{
switch(e->sig)
{
case Q_ENTRY_SIG:
PTPTRACE("Inactive\r\n");
return Q_HANDLED();
case SET_FRAMES_SIG:
me->frmCount = (uint16_t)((SetEvt*)e)->value;
return Q_HANDLED();
case SET_SELF_TIMEOUT_SIG:
me->selfTimeout = ((SetEvt*)e)->value;
return Q_HANDLED();
case SET_FRAME_TIMEOUT_SIG:
me->frameTimeout = ((SetEvt*)e)->value;
return Q_HANDLED();
case SET_BRACKETING_SIG:
me->bktStep = ((SetBktEvt*)e)->step;
me->bktNegative = ((SetBktEvt*)e)->negative;
me->bktPositive = ((SetBktEvt*)e)->positive;
return Q_HANDLED();
case RUN_SIG:
me->frmCntdn = me->frmCount;
me->bktCntdn = (me->bktStep) ? (me->bktPositive - me->bktNegative) / me->bktStep + 1 : 1;
me->bktPos = me->bktNegative;
return Q_TRAN(&HDRCapture::Active);
}
return Q_SUPER(&QHsm::top);
}
 
QState HDRCapture::Active(HDRCapture *me, QEvent const *e)
{
switch (e->sig)
{
case Q_ENTRY_SIG:
PTPTRACE("Active\r\n");
return Q_HANDLED();
case Q_EXIT_SIG:
PTPTRACE("::Q_EXIT_SIG\r\n");
return Q_HANDLED();
case Q_INIT_SIG:
PTPTRACE("Q_INIT_SIG\r\n");
return Q_TRAN(&HDRCapture::SaveSettings);
case RUN_SIG:
PTPTRACE("::RUN_SIG\r\n");
return Q_TRAN(&HDRCapture::SaveSettings);
case ABORT_SIG:
PTPTRACE("ABORT_SIG\r\n");
return Q_TRAN(&HDRCapture::RestoreSettings);
case PTP_RC_SIG:
PTPTRACE("::PTP_RC_SIG\r\n");
switch (((PTP_RC_Evt*)e)->rc)
{
case PTP_RC_OK:
me->qpEvt.sig = PTP_RC_OK_SIG;
me->theQueue.Push(&me->qpEvt);
return Q_HANDLED();
case PTP_RC_DeviceBusy:
me->toEvt.timeout = PTP_TIMEOUT;
me->toEvt.attribs = TA_PTP_TIMEOUT;
me->theQueue.Push(&me->toEvt);
return Q_TRAN(&HDRCapture::Timeout);
default:
return Q_TRAN(&HDRCapture::Inactive);
}
case SET_TIMEOUT_SIG:
PTPTRACE("::SET_TIMEOUT_SIG\r\n");
return Q_HANDLED();
case TIMEOUT_SIG:
PTPTRACE("::TIMEOUT_SIG\r\n");
return Q_TRAN(me->activeHistory);
case PTP_RC_OK_SIG:
PTPTRACE("::PTP_RC_OK_SIG\r\n");
return Q_TRAN(me->activeHistory);
case TICK_MILLIS_SIG:
PTPTRACE("::TICK_MILLIS_SIG\r\n");
return Q_HANDLED();
}
return Q_SUPER(&QHsm::top);
}
 
QState HDRCapture::SaveSettings(HDRCapture *me, QEvent const *e)
{
static bool bSaved = false;
switch (e->sig)
{
case Q_ENTRY_SIG:
PTPTRACE("SaveSettings\r\n");
me->activeHistory = (QStateHandler)&SaveSettings;
// me->rcEvt.rc = me->Eos.GetProperty(EOS_DPC_ExposureCompensation, me->bktOldVal);
me->rcEvt.rc = PTP_RC_OK;
me->theQueue.Push(&me->rcEvt);
me->bktOldVal = (uint8_t)0;
return Q_HANDLED();
case PTP_RC_OK_SIG:
PTPTRACE("PTP_RC_OK_SIG\r\n");
if (me->selfTimeout)
{
me->theQueue.Push((QEvent*)e);
return Q_TRAN(&HDRCapture::SelfTimer);
}
return Q_TRAN(&HDRCapture::PreCapture);
} // switch
return Q_SUPER(&HDRCapture::Active);
}
 
QState HDRCapture::SelfTimer(HDRCapture *me, QEvent const *e)
{
switch (e->sig)
{
case Q_ENTRY_SIG:
PTPTRACE("SelfTimer\r\n");
me->activeHistory = (QStateHandler)&SelfTimer;
return Q_HANDLED();
case TICK_MILLIS_SIG:
PTPTRACE("TICK_MILLIS_SIG\r\n");
return Q_TRAN(&HDRCapture::PreCapture);
case PTP_RC_OK_SIG:
PTPTRACE("PTP_RC_OK_SIG\r\n");
me->toEvt.timeout = me->selfTimeout;
me->toEvt.attribs = TA_SELF_TIMER;
me->theQueue.Push(&me->toEvt);
return Q_TRAN(&HDRCapture::Timeout);
case TIMEOUT_SIG:
PTPTRACE("TIMEOUT_SIG\r\n");
return Q_TRAN(&HDRCapture::PreCapture);
} // switch
return Q_SUPER(&HDRCapture::Active);
}
 
QState HDRCapture::RestoreSettings(HDRCapture *me, QEvent const *e)
{
switch (e->sig)
{
case Q_ENTRY_SIG:
PTPTRACE("RestoreSettings\r\n");
me->activeHistory = (QStateHandler)&RestoreSettings;
me->rcEvt.rc = me->Eos.SetProperty(EOS_DPC_ExposureCompensation, me->bktOldVal);
me->theQueue.Push(&me->rcEvt);
return Q_HANDLED();
case PTP_RC_OK_SIG:
return Q_TRAN(&HDRCapture::Inactive);
} // switch
return Q_SUPER(&HDRCapture::Active);
}
 
QState HDRCapture::PreCapture(HDRCapture *me, QEvent const *e)
{
switch (e->sig)
{
case Q_ENTRY_SIG:
PTPTRACE("PreCapture\r\n");
me->activeHistory = (QStateHandler)&PreCapture;
return Q_HANDLED();
case TICK_MILLIS_SIG:
PTPTRACE("TICK_MILLIS_SIG\r\n");
if (!me->bktCntdn)
{
me->bktCntdn = (me->bktStep) ? (me->bktPositive - me->bktNegative) / me->bktStep + 1 : 1;
me->bktPos = me->bktNegative;
}
if (me->bktStep)
return Q_TRAN(&HDRCapture::ExpCompSet);
return Q_TRAN(&HDRCapture::Capture);
} // switch
return Q_SUPER(&HDRCapture::Active);
}
 
QState HDRCapture::Capture(HDRCapture *me, QEvent const *e)
{
switch (e->sig)
{
case Q_ENTRY_SIG:
PTPTRACE("Capture\r\n");
me->activeHistory = (QStateHandler)&Capture;
me->rcEvt.rc = me->Eos.Capture();
// me->rcEvt.rc = PTP_RC_OK;
me->theQueue.Push(&me->rcEvt);
return Q_HANDLED();
case PTP_RC_OK_SIG:
PTPTRACE("PTP_RC_OK_SIG\r\n");
return Q_TRAN(&HDRCapture::PostCapture);
} // switch
return Q_SUPER(&HDRCapture::Active);
}
 
QState HDRCapture::PostCapture(HDRCapture *me, QEvent const *e)
{
switch (e->sig)
{
case Q_ENTRY_SIG:
PTPTRACE("PostCapture\r\n");
me->activeHistory = (QStateHandler)&PostCapture;
return Q_HANDLED();
case TICK_MILLIS_SIG:
PTPTRACE("TICK_MILLIS_SIG\r\n");
 
if (!me->bktCntdn)
return Q_TRAN(&HDRCapture::PreCapture);
 
me->bktPos += me->bktStep;
if (--me->bktCntdn == 0)
{
--me->frmCntdn;
me->OnFrameCaptured(me->frmCntdn);
}
me->OnBktFrameCaptured(me->bktCntdn);
 
// if it was the last frame in total
if (!me->frmCntdn)
{
me->qpEvt.sig = ABORT_SIG;
me->theQueue.Push(&me->qpEvt);
return Q_HANDLED();
}
if (me->bktCntdn)
return Q_TRAN(&HDRCapture::PreCapture);
 
// if it was the last frame in bracketing
me->toEvt.timeout = me->frameTimeout;
me->toEvt.attribs = TA_INTR_TIMER;
me->theQueue.Push(&me->toEvt);
return Q_TRAN(&HDRCapture::Timeout);
case TIMEOUT_SIG:
PTPTRACE("TIMEOUT_SIG\r\n");
return Q_TRAN(&HDRCapture::PreCapture);
}
return Q_SUPER(&HDRCapture::Active);
}
 
QState HDRCapture::ExpCompSet(HDRCapture *me, QEvent const *e)
{
switch (e->sig)
{
case Q_ENTRY_SIG:
PTPTRACE("ExpCompSet\r\n");
me->activeHistory = (QStateHandler)&ExpCompSet;
me->rcEvt.rc = me->Eos.SetProperty(EOS_DPC_ExposureCompensation, EXP_COMP_VALUE(me->bktPos));
// me->rcEvt.rc = PTP_RC_OK;
me->theQueue.Push(&me->rcEvt);
return Q_HANDLED();
case PTP_RC_OK_SIG:
PTPTRACE("PTP_RC_OK_SIG\r\n");
return Q_TRAN(&HDRCapture::Capture);
} // switch
return Q_SUPER(&HDRCapture::Active);
}
 
QState HDRCapture::Timeout(HDRCapture *me, QEvent const *e)
{
static uint32_t timeout = 0;
static uint32_t local_time = 0;
static uint32_t seconds_left = 0;
static uint8_t attribs = 0;
static uint16_t sec_cntdn = 1000;
switch (e->sig)
{
case Q_ENTRY_SIG:
PTPTRACE("Timeout\r\n");
return Q_HANDLED();
case SET_TIMEOUT_SIG:
attribs = ((SetTimeoutEvt*)e)->attribs;
timeout = (attribs & 0x01) ? ((SetTimeoutEvt*)e)->timeout * 1000 : ((SetTimeoutEvt*)e)->timeout;
if (attribs & 0x01)
{
seconds_left = ((SetTimeoutEvt*)e)->timeout;
sec_cntdn = 1000;
switch (attribs)
{
case TA_SELF_TIMER:
me->OnSelfTimerProgress(seconds_left);
break;
case TA_INTR_TIMER:
me->OnIntrTimerProgress(seconds_left);
break;
// case TA_BULB_TIMER:
// me->OnBulbTimerProgress(seconds_left);
// break;
} // switch
}
local_time = millis();
return Q_HANDLED();
case TICK_MILLIS_SIG:
uint32_t dt = local_time;
local_time = millis();
dt = local_time - dt;
timeout = (timeout < dt) ? 0 : timeout - dt;
 
if (attribs & 1)
{
bool bTick = (sec_cntdn <= dt);
sec_cntdn = (sec_cntdn > dt) ? sec_cntdn - dt : 1000 - dt;
if (bTick)
{
seconds_left --;
switch (attribs)
{
case TA_SELF_TIMER:
me->OnSelfTimerProgress(seconds_left);
break;
case TA_INTR_TIMER:
me->OnIntrTimerProgress(seconds_left);
break;
} // switch
} // if (--sec_cntdn == 0)
} // if (attribs & 1)
if (!timeout)
{
me->qpEvt.sig = TIMEOUT_SIG;
me->theQueue.Push(&me->qpEvt);
}
return Q_HANDLED();
} // switch
return Q_SUPER(&HDRCapture::Active);
}
 
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/hdrcapture.h
0,0 → 1,130
#if !defined(__HDRCAPTURE_H__)
#define __HDRCAPTURE_H__
 
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <qep_port.h>
#include <ptp.h>
#include <canoneos.h>
#include <simplefifo.h>
#include <valuelist.h>
 
#define PTP_TIMEOUT 250
 
#define TA_PTP_TIMEOUT 0x00
#define TA_SELF_TIMER 0x03
#define TA_INTR_TIMER 0x05
#define TA_BULB_TIMER 0x07
 
enum HDRCaptureSignals
{
TICK_MILLIS_SIG = Q_USER_SIG,
SET_FRAMES_SIG,
SET_SELF_TIMEOUT_SIG,
SET_FRAME_TIMEOUT_SIG,
SET_BRACKETING_SIG,
RUN_SIG,
ABORT_SIG,
TIMEOUT_SIG,
SET_TIMEOUT_SIG,
PTP_RC_SIG,
PTP_RC_OK_SIG
};
 
struct SetTimeoutEvt : public QEvent
{
uint32_t timeout;
uint8_t attribs;
};
 
struct SetEvt : public QEvent
{
uint32_t value;
};
 
struct SetBktEvt : public QEvent
{
uint8_t step;
uint8_t negative;
uint8_t positive;
};
 
struct PTP_RC_Evt : public QEvent
{
uint16_t rc;
};
 
class HDRCapture : public QHsm
{
uint16_t frmCntdn;
uint16_t frmCount;
uint32_t selfTimeout;
uint32_t frameTimeout;
uint8_t bktStep;
uint8_t bktNegative;
uint8_t bktPositive;
uint8_t bktCntdn;
uint8_t bktPos;
uint8_t bktOldVal;
CanonEOS &Eos;
SetTimeoutEvt toEvt;
PTP_RC_Evt rcEvt;
QEvent qpEvt;
QStateHandler activeHistory;
 
SimpleFIFO<QEvent*, 4> theQueue;
public:
HDRCapture(CanonEOS &eos) :
QHsm((QStateHandler)&HDRCapture::Initial),
frmCount(0),
frmCntdn(0),
selfTimeout(0),
frameTimeout(0),
bktStep(0),
bktNegative(0),
bktPositive(0),
bktCntdn(0),
bktPos(0),
bktOldVal(0),
Eos(eos),
activeHistory(NULL)
{
toEvt.sig = SET_TIMEOUT_SIG;
rcEvt.sig = PTP_RC_SIG;
};
void PostEvent(QEvent *e)
{
theQueue.Push(e);
};
void Run()
{
QEvent *e = NULL;
while ( (e = theQueue.Pop()) )
dispatch(e);
};
 
protected:
static QState Initial(HDRCapture *me, QEvent const *e);
static QState Inactive(HDRCapture *me, QEvent const *e);
static QState Active(HDRCapture *me, QEvent const *e);
static QState SelfTimer(HDRCapture *me, QEvent const *e);
static QState PreCapture(HDRCapture *me, QEvent const *e);
static QState Capture(HDRCapture *me, QEvent const *e);
static QState PostCapture(HDRCapture *me, QEvent const *e);
static QState ExpCompSet(HDRCapture *me, QEvent const *e);
static QState SaveSettings(HDRCapture *me, QEvent const *e);
static QState RestoreSettings(HDRCapture *me, QEvent const *e);
static QState Timeout(HDRCapture *me, QEvent const *e);
virtual void OnFrameCaptured(uint16_t left) {};
virtual void OnBktFrameCaptured(uint16_t left) {};
virtual void OnSelfTimerProgress(uint32_t left) {};
virtual void OnIntrTimerProgress(uint32_t left) {};
};
 
#endif // __HDRCAPTURE_H__
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/menu.cpp
0,0 → 1,39
#include "menu.h"
 
bool Menu::OnInitialState()
{
menuItems[itemSelected].screenItem->Highlight(true);
Screen::Set(screenId);
return true;
};
 
bool Menu::OnEncoderChanged(int8_t value)
{
menuItems[itemSelected].screenItem->Highlight(false);
int8_t new_val = (int8_t)itemSelected + value;
if (new_val < 0)
itemSelected = 0;
else if (new_val >= numItems)
itemSelected = numItems - 1;
else
itemSelected = (uint8_t)new_val;
menuItems[itemSelected].screenItem->Highlight(true);
 
return true;
};
 
bool Menu::OnEncButtonDown()
{
if (menuItems[itemSelected].ptrFunction)
(menuItems[itemSelected].ptrFunction)();
};
 
bool Menu::OnExtButtonDown()
{
if (returnState)
StateMachine::SetState(returnState);
};
 
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/menu.h
0,0 → 1,200
#if !defined(__MENU_H__)
#define __MENU_H__
 
#include <inttypes.h>
#include "screenitem.h"
#include "screen.h"
#include "controls.h"
 
typedef void (*MenuFunctionPtr)();
 
struct MenuItem
{
ScreenItem *screenItem;
MenuFunctionPtr ptrFunction;
};
 
class Menu : public ControlEvents
{
uint8_t numItems;
uint8_t itemSelected;
uint8_t screenId;
MenuItem *menuItems;
StateMachine *returnState;
public:
Menu(uint8_t scr, uint8_t num_items, MenuItem *items, uint8_t sel = 0, StateMachine *s = NULL) :
screenId(scr),
numItems(num_items),
menuItems(items),
itemSelected(sel),
returnState(s)
{};
void SetReturnState(StateMachine *s) { returnState = s; };
virtual bool OnInitialState();
virtual bool OnEncoderChanged(int8_t value);
virtual bool OnEncButtonDown();
virtual bool OnExtButtonDown();
};
 
typedef void (*SpinFunction)(DataItemBase *data_item);
 
template <class ITEM_TYPE, class VALUE_TYPE>
class IntSpin : public ControlEvents
{
VALUE_TYPE minValue;
VALUE_TYPE maxValue;
VALUE_TYPE incValue;
ITEM_TYPE *dataItem;
StateMachine *returnState;
SpinFunction pFunction;
 
public:
IntSpin(VALUE_TYPE min_val, VALUE_TYPE max_val, VALUE_TYPE inc_val, ITEM_TYPE *item, SpinFunction f) :
minValue(min_val),
maxValue(max_val),
incValue(inc_val),
dataItem(item),
returnState(NULL),
pFunction(f)
{
};
void SetConstraints(VALUE_TYPE min_val, VALUE_TYPE max_val, VALUE_TYPE inc_val)
{
minValue = min_val;
maxValue = max_val;
incValue = inc_val;
};
void SetReturnState(StateMachine *s) { returnState = s; };
virtual bool OnEncoderChanged(int8_t value)
{
int16_t new_val = dataItem->Get() + value * incValue;
if (new_val > maxValue)
new_val = maxValue;
else if (new_val < minValue)
new_val = minValue;
dataItem->Set((VALUE_TYPE)new_val);
dataItem->SetUpdated(true);
return true;
};
 
virtual bool OnEncButtonDown()
{
if (pFunction)
pFunction((DataItemBase*)dataItem);
if (returnState)
StateMachine::SetState(returnState);
return true;
};
};
 
template <class ITEM_TYPE, class VALUE_TYPE>
class EEPROMListIntSpin : public ControlEvents
{
EEPROMByteList *valueList;
ITEM_TYPE *dataItem;
StateMachine *returnState;
SpinFunction pFunction;
public:
EEPROMListIntSpin(EEPROMByteList *list, ITEM_TYPE *item, SpinFunction pf) :
valueList(list),
dataItem(item),
returnState(NULL),
pFunction(pf)
{
};
void SetReturnState(StateMachine *s) { returnState = s; };
virtual bool OnEncoderChanged(int8_t value)
{
if (valueList->GetSize() < 1)
return true;
VALUE_TYPE new_value;
if (value < 0)
new_value = valueList->GetPrev(dataItem->Get(), -value);
else
new_value = valueList->GetNext(dataItem->Get(), value);
dataItem->Set(new_value);
dataItem->SetUpdated(true);
return true;
};
 
virtual bool OnEncButtonDown()
{
if (pFunction)
pFunction((DataItemBase*)dataItem);
if (returnState)
StateMachine::SetState(returnState);
return true;
};
};
 
 
template <class ITEM_TYPE, class VALUE_TYPE, class VALUE_LIST_TYPE>
class SRAMListIntSpin : public ControlEvents
{
VALUE_LIST_TYPE *valueList;
ITEM_TYPE *dataItem;
StateMachine *returnState;
SpinFunction pFunction;
public:
SRAMListIntSpin(VALUE_LIST_TYPE *list, ITEM_TYPE *item, SpinFunction pf) :
valueList(list),
dataItem(item),
returnState(NULL),
pFunction(pf)
{
};
void SetReturnState(StateMachine *s) { returnState = s; };
virtual bool OnEncoderChanged(int8_t value)
{
if (valueList->GetSize() < 1)
return true;
VALUE_TYPE new_value;
if (value < 0)
new_value = valueList->GetPrev(dataItem->Get(), -value);
else
new_value = valueList->GetNext(dataItem->Get(), value);
dataItem->Set(new_value);
dataItem->SetUpdated(true);
return true;
};
 
virtual bool OnEncButtonDown()
{
if (pFunction)
pFunction((DataItemBase*)dataItem);
if (returnState)
StateMachine::SetState(returnState);
return true;
};
};
 
#endif // __MENU_H__
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/screen.cpp
0,0 → 1,43
#include "screen.h"
 
uint8_t Screen::currentScreen = 0;
uint8_t Screen::totalScreens = 0;
bool Screen::screenChanged = true;
 
Screen::Screen(const uint8_t num_items, ScreenItem *pItems) : numItems(num_items)
{
screenItems = (ScreenItem*)pgm_read_word(pItems);
if (totalScreens < MAX_SCREENS)
screenPool2[totalScreens++] = this;
};
 
void Screen::Update(Max_LCD *pLcd, bool initial)
{
for (uint8_t i=0; i<numItems; i++)
screenItems[i].Update(pLcd, initial);
};
 
void Screen::Set(uint8_t screen_id)
{
if (screen_id >= totalScreens)
return;
currentScreen = screen_id;
screenChanged = true;
};
 
void Screen::Run(Max_LCD *pLcd)
{
if (screenChanged)
{
pLcd->clear();
pLcd->home();
}
if (screenPool2[currentScreen])
{
screenPool2[currentScreen]->Update(pLcd, (screenChanged) ? true : false);
screenChanged = false;
}
}
 
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/screen.h
0,0 → 1,32
#if !defined(__SCREEN_H__)
#define __SCREEN_H__
 
#include <inttypes.h>
#include "screenitem.h"
 
#define MAX_SCREENS 12
 
class Screen;
 
static Screen *screenPool2[MAX_SCREENS];
 
class Screen
{
static uint8_t currentScreen;
static uint8_t totalScreens;
static bool screenChanged;
ScreenItem *screenItems;
const uint8_t numItems;
public:
Screen(const uint8_t num_items, ScreenItem *pItems);
static void Run(Max_LCD *pLcd);
static void Set(uint8_t screen_id);
static uint8_t Get() { return currentScreen; };
void Update(Max_LCD *pLcd, bool initial);
};
 
#endif // __SCREEN_H__
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/screenitem.cpp
0,0 → 1,89
#include "screenitem.h"
 
void ScreenItem::SetAttribs(uint8_t left, uint8_t top, uint8_t len, bool highlighted, bool pgm)
{
itemAttribs.bmLeft = left;
itemAttribs.bmTop = top;
itemAttribs.bmLen = len;
itemAttribs.bmHighlighted = (highlighted) ? 1 : 0;
itemAttribs.bmHlChanged = 1; // item highlighting changed flag
itemAttribs.bmPgmString = (pgm) ? 1 : 0;
};
 
ScreenItem::ScreenItem(uint8_t left, uint8_t top, uint8_t len, bool highlighted, DataItemBase *item) :
dataItem(item)
{
SetAttribs(left, top, len, highlighted, 0);
}
 
ScreenItem::ScreenItem(uint8_t left, uint8_t top, uint8_t len, bool highlighted, const char *item) :
dataItem((void*)item)
{
SetAttribs(left, top, len, highlighted, 1);
}
 
void ScreenItem::Print(Max_LCD *p)
{
char* str;
bool is_pgm = false;
if (itemAttribs.bmPgmString == 1)
{
is_pgm = true;
str = (char*)dataItem;
}
else
((DataItemBase*)dataItem)->GetText(&str, is_pgm);
if(!str)
return;
uint8_t cnt = 0;
if (is_pgm)
{
char c;
while((c = pgm_read_byte(str++)) && cnt < itemAttribs.bmLen)
{
p->print(c,BYTE);
cnt ++;
}
}
else
{
char *pc = str;
while(*pc && cnt < itemAttribs.bmLen)
{
p->print(*pc++,BYTE);
cnt ++;
}
}
}
 
void ScreenItem::Update(Max_LCD *pLcd, bool initial)
{
if (initial || ( itemAttribs.bmPgmString == 0 && ((DataItemBase*)dataItem)->IsUpdated() ) || itemAttribs.bmHlChanged)
{
pLcd->home();
if (itemAttribs.bmLeft > 0)
{
pLcd->setCursor(itemAttribs.bmLeft-1, itemAttribs.bmTop);
pLcd->print((itemAttribs.bmHighlighted) ? '>' : ' ', BYTE);
}
else
pLcd->setCursor(itemAttribs.bmLeft, itemAttribs.bmTop);
Print(pLcd);
if (itemAttribs.bmLeft + itemAttribs.bmLen < 16)
pLcd->print((itemAttribs.bmHighlighted) ? '<' : ' ', BYTE);
if (itemAttribs.bmPgmString == 0)
((DataItemBase*)dataItem)->SetUpdated(false);
itemAttribs.bmHlChanged = 0;
}
}
 
/C-OSD/arducam-osd/libraries/PTPCamera/examples/EOSCamController/screenitem.h
0,0 → 1,36
#if !defined(__SCREENITEM_H__)
#define __SCREENITEM_H__
 
#include <inttypes.h>
#include <Max_LCD.h>
#include "dataitem.h"
 
struct ScreenItemAttributes
{
uint16_t bmLeft : 4;
uint16_t bmTop : 2;
uint16_t bmLen : 5;
uint16_t bmHighlighted : 1;
uint16_t bmHlChanged : 1;
uint16_t bmPgmString : 1;
};
 
class ScreenItem
{
ScreenItemAttributes itemAttribs;
void *dataItem;
void Print(Max_LCD *p);
void SetAttribs(uint8_t left, uint8_t top, uint8_t len, bool highlighted, bool pgm);
public:
ScreenItem(uint8_t left, uint8_t top, uint8_t len, bool highlighted, DataItemBase *item);
ScreenItem(uint8_t left, uint8_t top, uint8_t len, bool highlighted, const char *item);
void Update(Max_LCD *pLcd, bool initial = true);
void Highlight(bool on) { itemAttribs.bmHighlighted = (on) ? 1 : 0; itemAttribs.bmHlChanged = 1; };
bool IsHighlighted() { return (itemAttribs.bmHighlighted == 1); };
};
 
#endif