/////////////////////////////////////////////////////////////////////////////////////
//  START USER DEFINED SETTINGS
/////////////////////////////////////////////////////////////////////////////////////
//  I2C Bus Expander setting (if used)
/////////////////////////////////////////////////////////////////////////////////////
#define PCF8574 0x40					
#define PCF8574A 0x70

#define I2CADR	PCF8574A	// used I2C bus expander chip to drive relays if any (must be dummy-declared also when no bus expander is used)
/////////////////////////////////////////////////////////////////////////////////////
//  Attenuator Device specific definitions
/////////////////////////////////////////////////////////////////////////////////////
#define ID "DG8SAQ Attenuator V1.0"	

#define DEFAULT_ATTEN 	0			// default dB value on first power-up
#define MIN_ATTEN		0			// minimum allowed attenuation in dB
#define DEFAULT_STEP 	0			// default step size index after first power up, (0...MAXSTEP), index of steps[]


#define CONFIGURATION3				// select YOUR configuration here!!!!!!!!!!!!!!!!
//////////////////////////// Configurations /////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
//Configuration1: Definitions for Tom's 1dB steps binary attenuator, PCF8574
#ifdef CONFIGURATION1	
	#define MIN_STEP		1			// minimum dB step size, information only for USB host
	unsigned char steps[] PROGMEM = {	// allowed step sizes in dB
		1,					// index 0
		2,					// index 1
		3,					// index 2
		5,					// index 3
		10,					// index 4
		20					// index 5
		};
	#define MAXSTEP 5					// highest allowed step size index 
	#define MAX_ATTEN		127			// maximum allowed attenuation in dB
	#define RELAYUPDATE	2				// max relay update rate in 20ms units, should be high for latching relays, i.e. 20 for 400ms
#endif
//////////////////////////////////////////////////////////////////////////
//Configuration2: Definitions for Weinschel 10dB steps attenuator, PCF8574
#ifdef CONFIGURATION2
	#define NONBINARY					// activate if non-binary step attenuator is to be used
	#define MIN_STEP		10			// minimum dB step size, information only for USB host
	unsigned char steps[] PROGMEM = {	// allowed step sizes in dB
		10,					// index 0
		20					// index 1
		};
	#define MAXSTEP 1					// highest allowed step size index
	#define MAX_ATTEN		90			// maximum allowed attenuation in dB 
	#define RELAYUPDATE	10				// max relay update rate in 20ms units, should be high for latching relays, i.e. 20 for 400ms
	unsigned char Ones[] PROGMEM = {	// one dB step control (non-binary)
		0,
		0,
		0,
		0,
		0,
		0,
		0,
		0,
		0,
		0
		};

	unsigned int Tens[] PROGMEM = {		// ten dB step control (non-binary, 10...90dB, 10-20-30-30-stages))
		0b0000,		//0dB
		0b0001,		//10dB
		0b0010,		//20dB
		0b0100,		//30dB
		0b0101,		//40dB,30+10
		0b0110,		//50dB,30+20
		0b1100,		//60dB,30+30
		0b1101,		//70dB,30+30+10
		0b1110,		//80dB,30+30+20
		0b1111		//90dB,30+30+20+10

		};
#endif
//////////////////////////////////////////////////////////////////////////
//Configuration3: Definitions for Weinschel 10dB steps attenuator, direct port access, no I2C bus expander
#ifdef CONFIGURATION3	
	#define NO_I2C_PORTEXPANDER			// activate if no I2C bus expander is being used
	//  Port Definitions //////////////////////////////////////////////////////////////////
	#define DDR0 	DDRB
	#define PORT_0 	PORTB
	#define P0		2

	#define DDR1 	DDRB
	#define PORT_1 	PORTB
	#define P1		3

	#define DDR2 	DDRB
	#define PORT_2 	PORTB
	#define P2		4

	#define DDR3 	DDRB
	#define PORT_3 	PORTB
	#define P3		5

	#define DDR4 	DDRC
	#define PORT_4 	PORTC
	#define P4		0

	#define DDR5 	DDRC
	#define PORT_5 	PORTC
	#define P5		1
	//  END Port Definitions //////////////////////////////////////////////////////////////
	#define NONBINARY					// activate if non-binary step attenuator is to be used
	#define MIN_STEP		10			// minimum dB step size, information only for USB host
	unsigned char steps[] PROGMEM = {	// allowed step sizes in dB
		10,					// index 0
		20					// index 1
		};
	#define MAXSTEP 1					// highest allowed step size index
	#define MAX_ATTEN		90			// maximum allowed attenuation in dB 
	#define RELAYUPDATE	10				// max relay update rate in 20ms units, should be high for latching relays, i.e. 20 for 400ms
	unsigned char Ones[] PROGMEM = {	// one dB step control (non-binary)
		0,
		0,
		0,
		0,
		0,
		0,
		0,
		0,
		0,
		0
		};

	unsigned int Tens[] PROGMEM = {		// ten dB step control (non-binary, 10...90dB, 10-20-30-30))
		0b0000,		//0dB
		0b0001,		//10dB
		0b0010,		//20dB
		0b0100,		//30dB
		0b0101,		//40dB,30+10
		0b0110,		//50dB,30+20
		0b1100,		//60dB,30+30
		0b1101,		//70dB,30+30+10
		0b1110,		//80dB,30+30+20
		0b1111		//90dB,30+30+20+10

		};
#endif
//////////////////////////// END Configurations ///////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////
//  END USER DEFINED SETTINGS
/////////////////////////////////////////////////////////////////////////////////////
 

/////////////////////////////////////////////////////////////////////////////////////
//  I2C Settings
/////////////////////////////////////////////////////////////////////////////////////

#define	I2C_BITRATE		40000			// kbs

#define I2CDDR 	DDRB
#define I2CPORT	PORTB
#define BIT_SDA	2
#define BIT_SCL 3
#define SDA		(1<<BIT_SDA)
#define SCL		(1<<BIT_SCL)
#include "I2CopenPE0FKO.h"

void i2c_outbyte(unsigned char i){
I2CPORT=I2CPORT &~( SDA | SCL);	// port lines must always be low
I2CSendStart();					// send I2C start sequence 
I2CErrors = 0;					// reset error counter
I2CSendByte(I2CADR);
I2CSendByte(i);
I2CSendStop();
}

void port_outbyte(unsigned char i){
DDR0=DDR0|(1<<P0);
DDR1=DDR1|(1<<P1);
DDR2=DDR2|(1<<P2);
DDR3=DDR3|(1<<P3);
DDR4=DDR4|(1<<P4);
DDR5=DDR5|(1<<P5);
char b,c;
//Port0
b=(i&1)<<P0;
c=PORT_0 & ~(1<<P0);
PORT_0=c | b;
//Port1
b=((i&2)>>1)<<P1;
c=PORT_1 & ~(1<<P1);
PORT_1=c | b;
//Port2
b=((i&4)>>2)<<P2;
c=PORT_2 & ~(1<<P2);
PORT_2=c | b;
//Port3
b=((i&8)>>3)<<P3;
c=PORT_3 & ~(1<<P3);
PORT_3=c | b;
//Port4
b=((i&16)>>4)<<P4;
c=PORT_4 & ~(1<<P4);
PORT_4=c | b;
//Port5
b=((i&32)>>5)<<P5;
c=PORT_5 & ~(1<<P5);
PORT_5=c | b;
}

/////////////////////////////////////////////////////////////////////////////////////
//  Attenuator Control
/////////////////////////////////////////////////////////////////////////////////////

#ifdef NONBINARY

	void SetDB(char att){
	int _ten=att/10;
	int _one=att;
	_one=_one-10*_ten;
	_one=pgm_read_byte(&Ones[_one]);
	_ten=pgm_read_word(&Tens[_ten]);
	#ifndef NO_I2C_PORTEXPANDER
	i2c_outbyte(_one | _ten);
	#else
	port_outbyte(_one | _ten);
	#endif
	}

#else 

	void SetDB(char att){
	#ifndef NO_I2C_PORTEXPANDER
	i2c_outbyte(att);
	#else
	port_outbyte(att);
	#endif
	}

#endif
