#include "Descriptors.h"


// *** Timer definitions ***
#ifndef TIMESTAMP
#define TIMESTAMP 1380000000 	// UTC 13-09-24 05:20:00
#define TZ 0
#endif

// *** Timer constant for 1s ***
#define TIMER_1000ms ( (2^16)-(F_CPU/256) - 15)
// echo `date +"ATRTCSET %s"` > /dev/temp0

#ifndef SHOW_RTC
#define SHOW_RTC 0
#endif
#define TIMER_SAVE_CONFIG 1800	// Write config and timestamp to eeprom every x seconds


// *** USB input buffer size ***
#ifndef SIZE_INPUT_BUFFER
#define SIZE_INPUT_BUFFER 25
#endif


// *** LCD Backlight ***
#ifndef PWM_LOOP_COUNT
#define PWM_LOOP_COUNT 500		// Default speed PWM loop cycle
#endif

#ifndef LCD_BL_PORT
#define LCD_BL_PORT PORTD
#define LCD_BL_DDR DDRD
#define LCD_BL_MASK (1 << PD0)
#endif


// *** Macros ***
#define DDR(x) (*(&x - 1))      /* address of data direction register of port x */
#define PIN(x) (*(&x - 2))      /* address of input register of port x          */
#define sbi(var, mask)   ((var) |= (uint8_t)(1 << mask))
#define cbi(var, mask)   ((var) &= (uint8_t)~(1 << mask))


// *** Button definitions ***
#ifdef BUTTONS
#define KEYB_KEEPALIVE_KEY HID_KEYBOARD_SC_LEFT_SHIFT	// Keep alive key to send every 256s
#define READCOUNT 5000			// Read input x times for status change
#define TOTAL_BUTTONS 1			// Number of buttons

struct button {
	volatile uint8_t *port;		// PORTx register
	uint8_t mask;				// BitMask
	uint8_t scancode;			// Keyboard scancode, 0 for none
	uint8_t status;				// Internal state
	uint16_t count;				// Internal count
};
struct button buttons[TOTAL_BUTTONS] = {
	{&PORTD, HWB_MASK, HID_KEYBOARD_SC_VOLUME_UP, 0, 0},
//	{&PORTD, (1<<PD1), 0, 0, 0},
};
#endif


// *** Relay output definitions ***
#ifdef RELAYS
#define TOTAL_RELAYS 7

struct relay {
	volatile uint8_t *port;		// PORTx register
	uint8_t mask;				// BitMask
};

struct relay relays[TOTAL_RELAYS] = {
	{&PORTB, (1 << PB4)},
	{&PORTB, (1 << PB5)},
	{&PORTB, (1 << PB6)},
	{&PORTC, (1 << PC4)},
	{&PORTC, (1 << PC5)},
	{&PORTC, (1 << PC6)},
	{&PORTC, (1 << PC7)},
//	{&PORTB, (1 << PB7)},
};
#endif


// *** Counter definitions ***
#ifdef COUNTER

// Port D1 INT1
#define COUNTER_PORT PORTD
#define COUNTER_MASK (1<<PD1)
#define COUNTER_INTERRUPT_VECTOR INT1_vect		// INT1 PD1
#define COUNTER_INTERRUPT INT1					// INT1 PD1
#define COUNTER_REGISTER_INIT EICRA |= (1<<ISC11); EICRA &= ~(1<<ISC10)

// Port D0 INT0
//#define COUNTER_MASK (1<<PD0)
//#define COUNTER_INTERRUPT_VECTOR INT0_vect		// INT1 PD0
//#define COUNTER_INTERRUPT INT0					// INT1 PD0
//#define COUNTER_REGISTER_INIT EICRA |= (1<<ISC01); EICRA &= ~(1<<ISC00)

//	EICRA &= ~(1<<ISC10);
//	EICRA |= (1<<ISC11);
//	EICRA |= (1<<ISC11) | (1<<ISC10);

#define COUNTER_MINOR_OVERFLOW 10000
#define COUNTER_MINOR_REPORT 50

#endif



// *** No config below ***


#define STRINGIFY(x) #x
#define EXPAND(x) STRINGIFY(x)

const char AT[] PROGMEM	  = "AT";
const char OK[] PROGMEM   = "OK\r\n";
const char CRLF[] PROGMEM = "\r\n";
const char COMPILEDATE[] PROGMEM = EXPAND(TIMESTAMP);

// *** General Commands ***
/*
	ATf: 	Flash, enter bootloader
	ATr: 	reboot
*/

// *** Status replies ***
const char REBOOTING[] PROGMEM = "Rebooting...";
const char ENTERING[] PROGMEM = "Entering ";
const char ENTER_BOOTLOADER[] PROGMEM = "DFU bootloader";


// *** LCD Commands ***

const char ATLCD[] PROGMEM       = "ATLCD";
#ifdef LCD
const char LCDINIT[] PROGMEM     = "ATLCDINIT";
const char LCDCLRSCR[] PROGMEM   = "ATLCDCLRSCR";
const char LCDHOME[] PROGMEM     = "ATLCDHOME";
const char LCDGOTOXY[] PROGMEM   = "ATLCDGOTOXY";
const char LCDPUTC[] PROGMEM     = "ATLCDPUTC";
const char LCDCMD[] PROGMEM      = "ATLCDCMD";
const char LCDBLON[] PROGMEM  	 = "ATLCDBLON";
const char LCDBLOFF[] PROGMEM    = "ATLCDBLOFF";
#endif

#ifdef PWM
const char LCDPWMSET[] PROGMEM   = "ATLCDPWMSET";
const char LCDPWMLOOP[] PROGMEM  = "ATLCDPWMLOOP";
const char LCDPWMCYCLE[] PROGMEM = "ATLCDPWMCYCLE";
#endif


// *** RTC Commands ***
#ifdef RTC
const char RTCSET[] PROGMEM		= "ATRTCSET";
const char RTCGET[] PROGMEM		= "ATRTCGET";
const char RTCOSET[] PROGMEM	= "ATRTCOSET";
const char RTCOGET[] PROGMEM	= "ATRTCOGET";
const char RTCON[] PROGMEM		= "ATRTCON";
const char RTCOFF[] PROGMEM		= "ATRTCOFF";
#ifdef TIME_H
const char RTCTZSET[] PROGMEM	= "ATRTCTZSET";
const char RTCTZGET[] PROGMEM	= "ATRTCTZGET";
const char RTCNOW[] PROGMEM		= "ATRTCNOW";
#endif
#endif


// *** Keyboard commands and replies
#ifdef KEYBOARD
#ifdef BUTTONS
const char ATKEYB[] PROGMEM   			= "ATKEYB";
const char KEYBSETKEY[] PROGMEM   		= "SETKEY";
const char KEYBGETKEY[] PROGMEM   		= "GETKEY";
const char KEYBSTATUS[] PROGMEM   		= "STATUS";
const char BTN_NOT_DEFINED[] PROGMEM 	= "Button not defined";
#endif
const char KEYBALIVEON[] PROGMEM  		= "ALIVEON";
const char KEYBALIVEOFF[] PROGMEM 		= "ALIVEOFF";
#endif


// *** Relay commands ***
#ifdef RELAYS
const char RELAYON[] PROGMEM   			= "ATRELAYON";
const char RELAYOFF[] PROGMEM   		= "ATRELAYOFF";
const char RELAY_NOT_DEFINED[] PROGMEM 	= "Relay not defined";
#endif


// *** Counter commands ***
#ifdef COUNTER
const char COUNTERMAJORSET[] PROGMEM   	= "ATCNTMJSET";
const char COUNTERMINORSET[] PROGMEM   	= "ATCNTMNSET";
const char COUNTERGET[] PROGMEM   		= "ATCNTGET";
const char COUNTEROVERFLOW[] PROGMEM	= "ATCNTOVERFLOW";
const char COUNTERREPORT[] PROGMEM		= "ATCNTREPORT";
#endif


// *** EEPROM Commands
//const char EEREAD[] PROGMEM		= "ATEEREAD";
const char EECLEAR[] PROGMEM	= "ATEECLEAR";


// *** Temperature Commands ***
const char ATT[] PROGMEM	= "ATT";
/*	ATTs: 	scan bus for sensors
	ATTl: 	list sensor
	ATTtn: 	show value for sensor n (1 <n< 3)
*/


// *** Temperature status replies ***
#ifdef TEMP
const char CRC_FAIL[] PROGMEM = "CRC FAIL"; 
const char CRC_OK[] PROGMEM = "CRC OK";
const char SENSORS_FOUND[] PROGMEM = "Sensors found: ";
#endif


// *** Date and time constants, only used for LCD output ***
#ifdef TIME_H
#if LCD_DISP_LENGTH >= 20
const char dayname[7][4] PROGMEM = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
const char monthname[12][4] PROGMEM = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
#endif
#endif



struct s_config {
	char signature[3];
	int32_t timestamp;
	int8_t timezone;
	int8_t show_rtc;
	int8_t lcd_bl;
	uint16_t pwm_loop_count;
	int8_t pwm_cycle;
	uint16_t timer_corr;
	#ifdef KEYBOARD
	uint8_t	keyb_keepalive;
	#ifdef BUTTONS	
	#endif
	uint8_t buttons[TOTAL_BUTTONS];
	#endif
	#ifdef RELAYS
	uint8_t relays[TOTAL_RELAYS];
	#endif
	#ifdef COUNTER
	uint32_t counter_major;
	uint16_t counter_minor;
	uint16_t counter_minor_overflow;
	uint16_t counter_minor_report;
	#endif
};



void SetupHardware(void);
#ifdef LCD
#ifdef RTC
void lcd_display_time(void);
#endif
#endif
void process_usb_cmd(void);