#ifndef CAMEDIA_H
#define CAMEDIA_H

#define OK 1
#define ERROR -1
#define TIMEOUT_ERROR -2
#define RETRY_ERROR -3
#define READ_TOO_FEW_ERROR -4
#define NULL_PTR_ERROR -5

#define TIMEOUT 5 /* five seconds */
#define MAX_RETRIES 3 /* if something goes wrong three times in same cmd, then stop it */

#define Camera_Signature 0x15
#define Camara_Action_Complete_Notification 0x05
#define Camera_Positive_Achnowledgement 0x06
#define Camera_Termination_Byte 0xff
#define Camera_Unable_to_Execute_Command 0x11

#define Computer_Initialization_Byte 0x00
#define Computer_Positive_Achnowledgement 0x06
#define Computer_Negative_Achnowledgement 0x15
#define Computer_Termination_Byte 0xff

#define Packet_Not_Last_in_Seq 0x02
#define Packet_Last_in_Seq 0x03
#define Packet_Command 0x1b
#define Packet_Subtype_First_Command 0x53
#define Packet_Subtype_Not_First_Command 0x43

/* Register definition */

/* Command_0 - SetIntgerRegister(..) */
enum Command_0 {
 Cmd_Set_Resolution=1,
 Cmd_Set_Clock,
 Cmd_Set_Shutter_Speed,
 Cmd_Set_Current_Frame_Number,
 Cmd_Set_Aperture,
 Cmd_Set_Color_Mode,
 Cmd_Set_Flash_Mode,
 Cmd_Set_Comm_Speed=17, 
 Cmd_Set_Bright_And_Contrast=19,
 Cmd_Set_White_Balance,
 Cmd_Set_Autoshut_on_Host_Timer=23,
 Cmd_Set_Autoshut_on_Field_Timer=24,
 Cmd_Set_LED=30,
 Cmd_Set_Lens_Mode=33,
 Cmd_Set_Date_Format=41,
 Cmd_Set_Exp_Meter=70,
 Cmd_Set_Optical_Mode=72};


/* Command_1 - ReadIntgerRegister(..) */
 enum Command_1 {
 Cmd_Get_Resolution=1,
 Cmd_Get_Clock,
 Cmd_Get_Shutter_Speed,
 Cmd_Get_Aperture=5,
 Cmd_Get_Color_Mode,
 Cmd_Get_Flash_Mode,
 Cmd_Get_Num_of_Frames_Taken=10,
 Cmd_Get_Num_of_Frames_Left,
 Cmd_Get_Length_of_Current_Frame,
 Cmd_Get_Length_of_Current_Thumbnail,
 Cmd_Get_Battery_Capacity=16,
 Cmd_Get_Comm_Speed, 
 Cmd_Get_Bright_And_Contrast=19,
 Cmd_Get_White_Balance,
 Cmd_Get_Autoshut_on_Host_Timer=23,
 Cmd_Get_Autoshut_on_Field_Timer=24,
 Cmd_Get_Available_Memory_Left=28,
 Cmd_Get_Lens_Mode=33,
 Cmd_Get_LCD_Brightness=35,
 Cmd_Get_LCD_Autoshut_Timer=38,
 Cmd_Get_Protect_State_of_Current_Frame,
 Cmd_Get_Date_Format=41,
 Cmd_Get_Exp_Meter=70,
 Cmd_Get_Optical_Mode=72};


/* Command_3 - SetVDRegister(..) */
enum Command_3 {
	Cmd_Set_Camera_ID=22,
	Cmd_Set_Serial_Number=25, 
	Cmd_Set_Model,
	Cmd_Set_Upload_Image=29}; 


/* Command_4 - ReadVDRegister(..) */	
enum Command_4 {
	Cmd_Get_Current_Frame=14,
	Cmd_Get_Current_Thumbnail,
	Cmd_Get_Camera_ID=22,
	Cmd_Get_Serial_Number=25,
	Cmd_Get_Version,
	Cmd_Get_Model,
	Cmd_Get_Audio_Data=44, /* not supported by many cameras */
	Cmd_Get_Camera_Summery_Data=46,
	Cmd_Get_Picture_Summery_Data,
	Cmd_Get_Manufacturer};
	

enum Resolution {
	Unknown_Resolution=-1,
	Standard_Resolution=1,
	High_Resolution,
	Extended_Resolution};

enum Aperture {
	Unknown_Aperture=-1,
	Low_Aperture=1,
	Midium_Aperture,
	High_Aperture};

enum Color_Mode {
	Unknown_Color_Mode=-1,
	Color_Color_Mode=1,
	BAW_Color_Mode=2};
	
enum Flash_Mode {
	Unknown_Flash_Mode=-1,
	Auto_Flash_Mode=0,
	Force_Flash_Mode,
	Off_Flash_Mode,
	Anti_Red_Eye_Flash_Mode,
	Slow_Sync_Flash_Mode};

enum Camera_Speed {
	CAMERA_SPEED_Unknown=-1,
	CAMERA_SPEED_INIT=0x0,
	CAMERA_SPEED_9600=0x1,
	CAMERA_SPEED_19200=0x2,
	CAMERA_SPEED_38400=0x3,
	CAMERA_SPEED_57600=0x4,
	CAMERA_SPEED_115200=0x5};


enum Bright_Contrast {
	Unknown_Bright_Contrast=-1,
	Normal_Bright_Contrast=0,
	More_Bright_Bright_Contrast,
	Less_Bright_Bright_Contrast,
	More_Contrast_Bright_Contrast,
	Less_Contrast_Bright_Contrast};

enum White_Balance {
	Unknown_White_Balance=-1,
	Auto_White_Balance=0,
	Skylight_White_Balance=1,
	Fluoresent_White_Balance=2,
	Thungsten_White_Balance=3,
	Cloudy_White_Balance=255};

enum Lens_Mode {
	Unknown_Lens_Mode=-1,
	Macro_Lens_Mode=1,
	Normal_Lens_Mode,
	Infinity_Fisheye_Lens_Mode};

enum Date_Format {
	Unknown_Date_Format=-1,
	YY_MM_DD_Date_Format=1,
	DD_MM_HH_Date_Format};

enum Exp_Meter {
	Unknown_Exp_Meter=-1,
	Center_weighted_Exp_Meter=1,
	Spot_Exp_Meter,
	Multi_Element_Matrix_Exp_Meter=5};

enum LED_Mode {
	Unknown_LED_Mode=-1,
	Off_LED_Mode=0,
	On_LED_Mode,
	Blink_LED_Mode};


#define L1 UBYTE
#define L2 UWORD
#define L4 ULONG 


/* SetInteger MACROS  (all Frame Independant) */

#define MACRO_Set_Integer(cmd, value)\
	SetIntegerRegister(cmd, value)\

/* GetInteger MACROS */

/* FD = Frame Dependant */
#define MACRO_Get_FD_Integer(framenumber, cmd)\
	SetIntegerRegister(Cmd_Set_Current_Frame_Number, (L1) framenumber);\
	ReadIntegerRegister(cmd, &r)\

/* FI = Frame Independant */
#define MACRO_Get_FI_Integer(cmd)\
	ReadIntegerRegister(cmd, &r);\


/* GetVData MACROS */
 
/* FD = Frame Dependant */
#define MACRO_Get_FD_VData(framenumber, cmd, buffer, size)\
	SetIntegerRegister(Cmd_Set_Current_Frame_Number, (L1) framenumber);\
	ReadVDataRegister(cmd, (L1 *) buffer, (L4 *) size)\
	

/* FI = Frame Independant */
#define MACRO_Get_FI_VData(cmd, buffer, size)\
	ReadVDataRegister(cmd, (L1 *) buffer, (L4 *) size)\

/*
struct Packet {
	L1 Packet_type;
	union {L1 Packet_subtype;
			 L1 Packet_sequence};
	L2 Length_of_data;
	Data *DataField;
	L2 checksum;
};
*/


enum Action_Code {
	AC_Erase_Last_Picture=0,
	AC_Erase_All_Picture,
	AC_Take_Picture,
	AC_Finish_Session_Immediatly=4,
	AC_Take_Preview_Snapshot,
	AC_Erase_Current_Frame,
	AC_Set_Protection_State=9,
	AC_Store_Freshly_Upload_Image_Into_NVRAM=11};

struct Command_0_Packet {
	L1 Packet_type;
	L1 Packet_subtype;
	L2 Length_of_data;

/* Begin of Command part */	
	L1 Command_Code;
	L1 Register_Number;
	L4 NewValue;
/* End of Command part */

	L2 checksum;
};


struct Command_1_Packet {
	L1 Packet_type;
	L1 Packet_subtype;
	L2 Length_of_data;

/* Begin of Command part */	
	L1 Command_Code;
	L1 Register_Number;
/* End of Command part */

	L2 checksum;
};


struct Command_2_Packet {
	L1 Packet_type;
	L1 Packet_subtype;
	L2 Length_of_data;

/* Begin of Command part */	
	L1 Command_Code;
	L1 Action_Code;
	L1 single_byte;
/* End of Command part */

	L2 checksum;
};

struct Command_3_Packet {
	L1 Packet_type;
	L1 Packet_subtype;
	L2 Length_of_data;

/* Begin of Command part */	
	L1 Command_Code;
	L1 Register_Number;
	L1 *vdata;
/* End of Command part */

	L2 checksum;
};

struct Command_4_Packet {
	L1 Packet_type;
	L1 Packet_subtype;
	L2 Length_of_data;

/* Begin of Command part */	
	L1 Command_Code;
	L1 Register_Number;
/* End of Command part */

	L2 checksum;
};



void bootstrap(char *serial_device, int unit);
void clean(int entrypoint);
void init(enum Camera_Speed cs);
void retr(void);
void SetSerialSpeed(enum Camera_Speed);

void read(L1 *, long);
__inline void read_L1(L1 *);
__inline void read_L2(L2 *);
__inline void read_L4(L4 *);

__inline L2 SetL2(L2);
__inline L4 SetL4(L4);

void send(L1 *, long);
__inline void send_L1(L1);
__inline void send_L2(L2);

void print_bytes(L1 *, long);
void save_Frame(int framenumber, char *name, char *comment);

__inline L2 SetL2(L2 a) {
        return (L2) ((((L1) (a & 0xff))<<8)+((L1) (a>>8)));
}

__inline L4 SetL4(L4 a) {
        return (L4) (((L1) (a & 0xff))<<24) + (((L1) ((a>>8) & 0xff))<<16) + (((L1) ((a>>16) & 0xff))<<8) + ((L1) (a>>24));
}

__inline L2 checksum(L1 *, L1 *);

void SetIntegerRegister(enum Command_0, L4);
void ReadIntegerRegister(enum Command_1, L4 *);
void TakeAction(enum Action_Code action, L1 arg);
void ReadVDataRegister(enum Command_4, L1 *, L4 *);


/* SetInteger functions */
void Set_Resolution(Resolution re);
void Set_Clock(time_t c);
void Set_Shutter_Speed(long ss);
/* Set_Current_Frame_Number doesn't make sense on this level */
void Set_Aperture(enum Aperture a);
void Set_Color_Mode(enum Color_Mode cm);
void Set_Flash_Mode(enum Flash_Mode fm);
void Set_Comm_Speed(enum Camera_Speed cs);
void Set_Bright_And_Contrast(enum Bright_Contrast bc);
void Set_White_Balance(enum White_Balance wb);
void Set_Autoshut_on_Host_Timer(int aoht);
void Set_Autoshut_on_Field_Timer(int asoft);
void Set_LED(enum LED_Mode lm);
void Set_Lens_Mode(enum Lens_Mode lm);
void Set_Date_Format(enum Date_Format df);
void Set_Exp_Meter(enum Exp_Meter em);
void Set_Optical_Mode(int AEL_WBL, int Fisheye, int Wide, int Digital_Zoom, int BAW);
 

/* GetInteger functions */
void Get_Resolution(Resolution *re);
void Get_Clock(time_t *c);
void Get_Shutter_Speed(long *ss);
void Get_Aperture(enum Aperture *a);
void Get_Color_Mode(enum Color_Mode *cm);
void Get_Flash_Mode(enum Flash_Mode *fm);
void Get_Num_of_Frames_Taken(int *noft);
void Get_Num_of_Frames_Left(int *nofl);
void Get_Length_of_Frame(int framenumber, long *locf);
void Get_Length_of_Thumbnail(int framenumber, long *loct);
void Get_Battery_Capacity(int *bc);
void Get_Comm_Speed(enum Camera_Speed *cs);
void Get_Bright_And_Contrast(enum Bright_Contrast *bc);
void Get_White_Balance(enum White_Balance *wb);
void Get_Autoshut_on_Host_Timer(int *aoht);
void Get_Autoshut_on_Field_Timer(int *asoft);
void Get_Available_Memory_Left(long *aml);
void Get_Lens_Mode(enum Lens_Mode *lm);
void Get_LCD_Brightness(int *lb);
void Get_LCD_Autoshut_Timer(int *lat);
void Get_Protect_State_of_Frame(int framenumber, int *psof);
void Get_Date_Format(enum Date_Format *df);
void Get_Exp_Meter(enum Exp_Meter *em);
void Get_Optical_Mode(int *AEL_WBL, int *Fisheye, int *Wide, int *Digital_Zoom, int *BAW);


/* GetVData functions */
void Get_Frame(int framenumber, UBYTE *buffer, long *size);
void Get_Thumbnail(int framenumber, UBYTE *buffer, long *size);
void Get_Camera_ID(UBYTE *buffer, long *size);
void Get_Serial_Number(UBYTE *buffer, long *size);
void Get_Version(UBYTE *buffer, long *size);
void Get_Model(char *string, long *size);
void Get_Audio_Data(UBYTE *buffer, long *size); /* not supported by many cameras */
void Get_Camera_Summery_Data(enum Resolution *re, int *LCD_Brightness, int *Frames_Taken);
void Get_Picture_Summery_Data(int framenumber, long *AudioDataLength, enum Resolution *re, int *ProtectionState, time_t *TimeDate);
void Get_Manufacturer(char *string, long *size);

/* Get_Preview function */

void Get_Preview(UBYTE *buffer, long *size);

/* dump functions for printouts */
char* dump(Resolution r);
char* dump(Aperture a);
char* dump(Color_Mode cm);
char* dump(Flash_Mode fm);
char* dump(Camera_Speed cs);
char* dump(Bright_Contrast bc);
char* dump(White_Balance wb);
char* dump(Lens_Mode lm);
char* dump(Date_Format df);
char* dump(Exp_Meter em);
char* dump(LED_Mode lm);

#endif