/*********************************

	servo2go.h
	
	Author:
	    Ryan Findley
	    
	version:
	    1.1

	Description:
		  
	An object-oriented approach to the servo2go card.
	The software which we got with the card failed to compile,
	and was hard to understand. This attempts to make it easier.
	
	Limitations:
	
	This class should work for multiple s2go cards. Multiple modules
	(or processes) that use this class might run into problems if they
	all try to use the same ports. Also, only one process should call
	the init() function, or it might wipe out config values from other
	processes.

	Only one card can be accessed using the Interrupt-on-EOC method for 
	analog-to-digital conversions.
	
	History:
	
	8/4/99	ryan	started
	8/9/99	ryan	finished basics, tested. (no ADC yet)
	8/10/99	ryan	tried to implement EOC interrupt... failed
	8/12/99	ryan	cleaned up a bit, added init() function.
					added ADCmode function.
	8/12/99 ryan	ADC still doesn't work.
	8/13/99	ryan	wrote ADC code... still has to be tested
	02/25/00 wbg 	rewrote ADC code	
***********************************/  

#ifndef SERVO2GO_H_INCLUDED
#define SERVO2GO_H_INCLUDED


//---------- include files -----------
#include <sys/types.h>
#include <s2g_offsets.h>

//---------- public definitions ------

//digital port directions
const int dInput = 1;
const int dOutput = 0;


//encoder quadratures
const int QUADRATURE_NONE = 0;
const int QUADRATURE_1    = 1;
const int QUADRATURE_2    = 2;
const int QUADRATURE_4    = 3;


//ADC
const float BITS2VOLTS = (5.0/4096);

// toggle
#define LOW  0
#define HIGH 1

//DAC and ADC ports, in an array for easy use
const off_t DACport[8] = { DAC_0, DAC_1, DAC_2, DAC_3, DAC_4, DAC_5, DAC_6, DAC_7 };
const off_t ADCport[8] = { ADC_0, ADC_1, ADC_2, ADC_3, ADC_4, ADC_5, ADC_6, ADC_7 };


#ifndef BYTE
	typedef unsigned char BYTE;
#endif
typedef unsigned char byteMask;
	    	

//- defines for the interrupt sources
typedef enum servo2goInterruptSources {
	S2G_EOC_INT =	0x08,	//end-of-conversion
	S2G_UI_INT =	0x02,	//user-generatable
	S2G_TP0_INT =	0x04,	//timer 0
	S2G_TP2_INT =	0x01,	//timer 2
	S2G_IXEVN_INT =	0x80,	//index pulses...
	S2G_IXODD_INT =	0x40,
	S2G_LIXEVN_INT=	0x20,	//latched interrupts for index pulses...
	S2G_LIXODD_INT=	0x10
} intSrc;





//---------- class definitions -------


class servo2go
{
  public:
    servo2go(off_t addressBase);
	virtual ~servo2go() {}
		
	//general setup and initialization
	init();											// inits the interrupt controller, resets ports, default IRQ = 5.
	zeroAll();										// zeroes all DAC outputs, sets digital I/O to inputs.
	int setIRQ( int );								// selects an IRQ. returns -1 on error, otherwise returns same as argument.
	enableInterrupt( intSrc );
	disableInterrupt( intSrc );						// disables the selected interrupt source
	//generateUserInterrupt();						// generates a "user" interrupt
    int setTimerPeriod( off_t whichTimer, 			// use TIMER_0, TIMER_1, or TIMER_2	
			unsigned long timerPeriodMicroSeconds);		
    

	//digital I/O    
	setDigitalDirections( int portA  = dInput, 
						  int portB  = dInput, 		// use dInput and dOutput.	
						  int portCL = dInput, 		// or use zero(output) or non-zero(input)
						  int portCH = dInput, 		// CL = lower port C, CH = upper port C
						  int portD  = dInput );									
    digitalOut( off_t whichPort, BYTE value);		// use PORT_A PORT_B PORT_C etc.
    digitalOutCBit( int whichBit, int hiLo );		// port C only: modifies 1 bit only (0 - 7)
    BYTE digitalIn( off_t whichPort);				// use PORT_A PORT_B PORT_C etc.
    
	//analog I/O
	virtual DAC( off_t whichPort, float value );	// use DAC_0 DAC_1 etc. OR DACport[i] (i= 0 -> 7)
													// virtual function for redefinition for dexter
	toggleDACport(off_t whichPort, float voltage);
	float readADC( off_t whichPort );				// use ADC_0 ADC_1 etc. OR ADCport[i] (i= 0 -> 7)
	startSingleADConversion( off_t whichPort );		//  
	int checkEOCflag (); 
	float readADCpoll ( off_t whichPort );			// polls EOC bit
    setADCautoZero(int onOff);						// 0 for auto-zero off, non-zero for auto-zero on.
	
	//encoders
    initEncoders( int quadrature = QUADRATURE_4 );	// zeros the encoders, inits.
    zeroEncoders( byteMask which = 0xff );			// presets the encoders to 0x7FFFFF, halfway in 24 bits.
    latchEncoders();								// (TIMER_0 interrupt will automatically latch encoders).			
    long readEnc( int which );						// use 0 - 7 for which encoder. Latch before reading.
    readEnc2( int which, long values[2]);			// even encoders only!!! 
													// This is a more efficient way to read 2 encoders
  
  protected:
    off_t	 wbase;									// the card's base address

};
    
    

#endif //SERVO2GO_H_INCLUDED