#ifndef __OUTPUT_H__
#define __OUTPUT_H__

#include <inttypes.h>

#define CMD_EVEN 0x1100
#define CMD_ODD 0x1200

#ifdef __cplusplus
extern "C"{
#endif

inline void initOutput() {
	
	pinMode_OUT_CLK_OUT;
	pinMode_OUT_DAT_OUT;
	pinMode_OUT_LED_LTC_OUT;
	pinMode_OUT_REL_LTC_OUT;
	pinMode_EXP_CLK_OUT;
	pinMode_EXP_DAT_OUT;
	pinMode_EXP_LTC_OUT;

	digitalWrite_OUT_LED_LTC_LOW;
	digitalWrite_OUT_REL_LTC_LOW;
}

inline void loadSerialRegisters(uint16_t value) {
	for (uint8_t i = 0; i < 16; i++)  {
		digitalWrite_OUT_DAT(value & (1 << (15-i)));		
		digitalWrite_OUT_CLK_HIGH;
		digitalWrite_OUT_CLK_LOW;		
	}
}

inline void setLedOutput() {
	digitalWrite_OUT_LED_LTC_HIGH;    
	delayMicroseconds(60);
    digitalWrite_OUT_LED_LTC_LOW;
}

inline void setRelayOutput() {
	digitalWrite_OUT_REL_LTC_HIGH;
	delayMicroseconds(60);
	digitalWrite_OUT_REL_LTC_LOW;
}

inline void setOutput() {
	digitalWrite_OUT_LED_LTC_HIGH;
	digitalWrite_OUT_REL_LTC_HIGH;
    
	delayMicroseconds(60);
    
	digitalWrite_OUT_LED_LTC_LOW;
	digitalWrite_OUT_REL_LTC_LOW;
}

inline void setDigitalPot(uint8_t index, uint8_t value) {
	uint16_t cmd = ((index % 2) ? CMD_ODD : CMD_EVEN) + value;
	
	digitalWrite_EXP_LTC_LOW;

	for (uint8_t i = 0; i < 16; i++)  {
		digitalWrite_EXP_DAT(cmd & (1 << (15-i)));		
		digitalWrite_EXP_CLK_HIGH;
		digitalWrite_EXP_CLK_LOW;		
	}
  
	for(uint8_t i = 0; i < index/2; i++) {
		for (uint8_t i = 0; i < 16; i++)  {
			digitalWrite_EXP_DAT_LOW;		
			digitalWrite_EXP_CLK_HIGH;
			digitalWrite_EXP_CLK_LOW;		
		}
	}
  
	digitalWrite_EXP_LTC_HIGH;
}

inline void setDigitalPots(uint8_t* values) {
	digitalWrite_EXP_LTC_LOW;
	uint16_t cmd;
	
	for(int8_t j = 4; j >= 0; j--) {
		cmd = CMD_ODD + values[j*2 + 1];
		for (uint8_t i = 0; i < 16; i++)  {
			digitalWrite_EXP_DAT(cmd & (1 << (15-i)));		
			digitalWrite_EXP_CLK_HIGH;
			digitalWrite_EXP_CLK_LOW;		
		}
	}
 
	digitalWrite_EXP_LTC_HIGH;
	digitalWrite_EXP_LTC_LOW;
		
	for(int8_t j = 4; j >= 0; j--) {
		cmd = CMD_EVEN + values[j*2];
		for (uint8_t i = 0; i < 16; i++)  {
			digitalWrite_EXP_DAT(cmd & (1 << (15-i)));		
			digitalWrite_EXP_CLK_HIGH;
			digitalWrite_EXP_CLK_LOW;		
		}
	}
	
	digitalWrite_EXP_LTC_HIGH;
}

inline void setAllOutputs(uint8_t* digitalPots, uint16_t serialOut) {
	loadSerialRegisters(serialOut);
	
	digitalWrite_OUT_LED_LTC_HIGH;
	digitalWrite_OUT_REL_LTC_HIGH;
	
	setDigitalPots(digitalPots);
	
	digitalWrite_OUT_LED_LTC_LOW;
	digitalWrite_OUT_REL_LTC_LOW;	
}

#ifdef __cplusplus
} // extern "C"
#endif

#endif
