#define   DEBUG
         
#ifdef   DEBUG 
   #define dprint(x)         Serial.print(x)
   #define dprintHex(x,HEX)  Serial.print(x,HEX)
   #define dprintln(x)       Serial.println(x)
   #define D(x)              x 
 #else  
   #define dprint(x)     
   #define dprintln(x)   
   #define dprintHex(x,HEX)   
   #define D(x)       
#endif   

#define u8t               uint8_t
#define u16t              uint16_t
#define u32t              uint32_t
#define i8t               int8_t
#define i16t              int16_t
#define i32t              int32_t

// pins definition
#define CurfAnalog        6
#define BatAnalog         7
#define ButtonPin         4
#define MotorOnPin        7
#define PwmOpenPin        6
#define PwmClosePin       5
#define PwmOutputPin      3
#define ChargePin         14
#define LimitPin          15
#define ImpulsePin        16
#define LedPin            17

// command group - ID
#define IdMasterS         0x10    // secure master command
#define IdRemoteS         0x20    // secure remote controller 
#define IdGateS           0x21    // secure gate commands

// system commands
#define CmdAck            1       // acknowledge 
#define CmdRegister       2       // sending Register
#define CmdSendStatus     6       // send status - once/ periodicaly
#define CmdDataStatus     7       // returning status
#define CmdSendRandom     8       // send random number 
#define CmdDataRandom     9       // returning random number 

// read write commands
#define CmdEepromWrite    0x30    // write to  EEPROM control structure
#define CmdEepromRead     0x31    // read from EEPROM control structure
#define CmdEepromData     0x32    // readed from EEPROM control structure
#define CmdRamWrite       0x34    // read from RAM control structure
#define CmdRamRead        0x35    // write to  RAM control structure
#define CmdRamData        0x36    // readed from RAM control structure

// gate command 
#define CmdGateOposite    0x40    // if opened close, if closed open
#define CmdGateOpen       0x41        
#define CmdGateClose      0x42        
#define CmdWingOposite    0x43        
#define CmdWingOpen       0x44              
#define CmdWingClose      0x45        
#define CmdGateStop       0x46      
#define CmdGateMaster     0x47    // for slave - register master wing

// remote commands
#define CmdRemoteKey      0x51    // remote key command    
#define CmdRemoteFunction 0x52    // remote function command    

// basic definitions
#define BufferSize        74      // transmit / receive buffer size 10 command + 64 max data length
#define DevicesMax        10      // maximum devices available for registartion
#define CounterWindow     1024    // receive counter for authentication command

// motor control definitions
#define CurrentResolution 1           // 1 currens range 5.5 A / resolution 21.5 mA 
                                      // 2 currens range 11 A / resolution 43 mA 
                                      // 4 currens range 22 A / resolution 86 mA 
#define CurrentFilterSamples   30    // filter time for integration values
#define CurrentValues          16      // current vaules stored for moving average and max current computation
#define Current1A              46.5455 // AD constant for current 1A
#define CurrentMax             0.15 * Current1A // maximum curent for motor switch off current * constant
#define CurrentStoreValues     60      // size of current store array
#define CurrentStoreFastSamples 15     // in phase 1 store this number of samples
#define CurrentStoreAverages   20      // in phase 2 average this number of samples before store
#define DirectionOpen          true    // motor direction for open gate
#define DirectionClose         false   // motor direction for close gate
#define GateTimeout            64      // timeout for motor in s
#define MotorOffTime           400     // minimum motor off time in ms
#define MotorHighSpeed         254     // maximum motor speed
#define MotorLowSpeed          128     // lower motor speed

// button definitions
#define ButtonShort       1       // short push code
#define ButtonLong        2       // long push code
#define ButtonExtra       3       // extra long push code
#define ButtonShortTime   50      // time in MS for short push
#define ButtonLongTime    2000    // time for long push
#define ButtonExtraTime   8000    // time for extra long push

// mode definitions
#define ModeBasic         0        // basic mode of operation
#define ModeLearn         1        // waiting for remote Register 
#define ModeFunctionSet   2        // after registering wait for function set - timeout 
#define ModeLearnTimeout  10000    // learn mode maximum time in ms 
#define RegisterTimeout   250      // wait for Register confirmation from master in ms 

// other definitions
#define Encrypt           0
#define Decrypt           1
#define FunctionMax       6       // maximum function number available
#define Counters          4       // number of  counters


uint8_t  receivePacket();
uint8_t  getPacketDevice();
uint8_t  searchSerialn(uint32_t serialn, uint8_t from); 
bool     checkCounterRx(uint8_t device);
uint8_t  getRemoteFunction(uint8_t device);
bool     addNewDevice();
bool     addRemoteFunction(uint8_t device);

void     sendCommand(uint8_t to, uint8_t command, uint16_t par1 = 0, uint16_t par2 = 0);
void     sendPacket (uint8_t id, uint8_t to, uint8_t len);
uint32_t getCounterTx();

void     removeAllDevices();
void     setBasicMode();
void     setLearnMode(uint8_t add=0);
void     stopLearnMode(uint8_t succesfull);

void intInit();
ISR(TIMER1_COMPA_vect);

void    ledPulse(uint8_t pulses, uint16_t pulseOnTime = 100, uint16_t pulsePeriod = 1000);
void    ledPulseWait(uint8_t pulses, uint16_t pulseOnTime = 100, uint16_t pulsePeriod = 1000 );
bool    motorOn( bool motorDir,  uint8_t motorCmd, uint8_t motorSpeed);
void    motorOff();
void    adcInit();
void    variableInit();
void    pinsInit();


/*
typedef enum  id{
      Ack = 1,                       
      Remote,
      Wing,
      Memory
} idt;
*/

typedef struct remote {
  uint32_t  serialn;
  uint32_t  counter;  
  uint8_t   command;            // command
  uint8_t   battery;            // resolution 10mV, offset -2V, range 2 to 4.55V
  int8_t    temperature;        // resolution 1 degree Celsius
  uint8_t   button;             // button pushed  
  uint8_t   function;           // aletrantive function command  
  uint8_t   rez[3];
} remotet;

typedef struct gateState {
  uint32_t  serialn;
  uint32_t  counter;  
  uint8_t   command;            // command = CmdDataStatus
  uint8_t   state;              // running / stopped
  uint8_t   battery;            // resolution 10mV, offset -2V, range 2 to 4.55V
  int8_t    temperature;        // resolution 1 degree Celsius
  uint16_t  runTime;            // run time in ms
  uint16_t  current;            // current time in ms
  uint8_t   angle;              // angle of gate - if available
} gateStatet;


typedef struct gateCmd {
  uint32_t  serialn;
  uint32_t  counter;  
  uint8_t   command;            // command = CmdDataStatus
  uint8_t   subCommand;         // subcommand if available
  uint16_t  par[3];             // command parameters - command specific
} gateCmdt;

typedef struct memCmd {
  uint32_t  serialn;
  uint32_t  counter;  
  uint8_t   command;            // CmdReadEeprom, CmdWriteEeprom, CmdReadRam,CmdWriteRam
  uint8_t   index;              // subcommand if available
  uint8_t   par[64];            // command data - only for write
} memCmdt;


typedef struct ramDevice {
  int8_t      temperature;       // actual temperature, resolution 1 degree Celsius
  uint8_t     battery;           // battery voltage, resolution 100mV, offset -5V, range 5 - 29.5 V
} ramDevicet;


typedef struct ramBase {         // RAM structure
  uint8_t     temperature;       // actual temperature
  uint8_t     battery;           // battery voltage
  uint16_t    gateOpenTime;      // learned full open time - maximum of histogram
  uint16_t    gateTimeout;       // gate timeout to stop moving  ??
 volatile uint16_t gateTime;     // current gate time in milisecond  - equivalent to angle openening
  uint8_t     gateAngle;         // gate angle opening in degress, 0 = closed
 volatile uint8_t  gateCurrent[60]; // max current in time resolutiom 0.019531A, up to 5A
  uint16_t     vbatMin;          // minimum battery voltage for charging
  uint16_t     vbatMax;          // maximum battery voltage for charging

//  uint8_t     gateOpenTimes[60]; // open time histogram  +/- 5 to 64s
  ramDevicet  device[DevicesMax];  // device records
} ramBaset;  


//  data structure - remote controller
typedef struct device {
  uint32_t    serialn;           // low byte = address of transmitter in range 1 - 239
  uint32_t    counter[Counters];   // receive counters
  uint8_t     type;              // type of device, remote and others
  uint8_t     function[15];      // function for all combination of 4 keys except 0 (no key) 
} devicet;  


typedef struct base {
  uint8_t     key[16];          // encryption key
  uint16_t    counterWindow;    // size of receive counter window
  uint8_t     devices;          // number of registered devices
  uint8_t     masterWingIdx;    // master address wing device index, if zero no master is present  
  uint8_t     slaveWingIdx;     // slave address wing device index, if zero no slave is present
  uint8_t     batteryAlarmIdx;  // address to send alarm if registered in devices, 0 = none
  uint8_t     vbatMin;          // minimum battery voltage for charging
  uint8_t     vbatMax;          // maximum battery voltage for charging
  uint8_t     vbatAlarm;        // battery voltage to send alarm
  uint8_t     vbatRemoteAlarm;  // remote battery voltage to send alarm
  uint8_t     gateDelay;        // slave gate leaf delay in seconds
  uint8_t     gateTimeout;      // gate timeout to stop moving  in seconds
  uint8_t     motorHighSpeed;   // motor speed 1 - 254
  uint8_t     motorLowSpeed;    // motor speed 1 - 254  
  
  devicet     device[DevicesMax];  
} baset;  


typedef union buffer {
  uint8_t     buf[BufferSize];
  remotet     remote;
  gateCmdt    gateCmd;
  gateStatet  gateState;
  memCmdt     memCmd;
} buffert;

