#include "maussensor.h"

Maussensor::Maussensor() {
}


Maussensor::~Maussensor() {
}


// Initialisiert den Maussensor
void Maussensor::init(int index) {
	// Setze die Pins entsprechend dem übergebenen Index
	if(index == MAUSSENSOR0) {
		sda_pin = MAUS0_SDA;
		sck_pin = MAUS0_SCK;
	}
	else {
		sda_pin = MAUS1_SDA;
		sck_pin = MAUS1_SCK;
	}

	// Initialisiere den Maussensor
	maus_sens_init();
}

// Gibt die X-Koordinate Zurück
uint8 Maussensor::GetX() {
	return maus_sens_read(MOUSE_DELTA_X_REG);
}

// Gibt die Y-Koordinate Zurück
uint8 Maussensor::GetY() {
	return maus_sens_read(MOUSE_DELTA_Y_REG);
}

/*!
 * Gibt den SQUAL-Wert zurueck. Dieser gibt an, wieviele Merkmale der Sensor 
 * im aktuell aufgenommenen Bild des Untergrunds wahrnimmt
 */
uint8 Maussensor::GetSqual() {
	return maus_sens_read(MOUSE_SQUAL_REG);
}

/*!
 * Uebertraegt ein Byte an den Sensor
 * @param data das Byte
 */
void Maussensor::maus_sens_writeByte(uint8 data){
	int8 i;
	MAUS_DDR  |= (1<<sda_pin); 		// SDA auf Output
	
	for (i=7; i>=0; i--){
		MAUS_PORT &= ~(1<<sck_pin);		// SCK auf Low, vorbereiten
		
		//Daten rausschreiben
		MAUS_PORT = (MAUS_PORT & (~MAUS_PIN)) |  ((data >> (7 - sda_pin)) & (1<<sda_pin));	
		data = data <<1;		// naechstes Bit vorbereiten
		asm volatile("nop"); 			// Etwas warten 
		
		MAUS_PORT |= (1<<sck_pin);		// SCK =1 Sensor uebernimmt auf steigender Flanke
	}
}

/*!
 * Liest ein Byte vom Sensor
 * @return das Byte
 */
uint8 Maussensor::maus_sens_readByte(void){
	int i;
	char data=0;

	MAUS_DDR  &= ~(1<<sda_pin); 	// SDA auf Input

	for (i=7; i>-1; i--){
		MAUS_PORT &= ~(1<<sck_pin);		// SCK =0 Sensor bereitet Daten auf fallender Flanke vor !
		data=data<<1;					// Platz schaffen

		asm volatile("nop"); 					// Etwas warten 
		MAUS_PORT |= (1<<sck_pin);		// SCK =1 Daten lesen  auf steigender Flanke
		
		data |= (MAUS_PIN >> sda_pin) & 0x01;			//Daten lesen
	}

	return data;
}

/*!
 * Uebertraegt ein write-Kommando an den Sensor
 * @param adr Adresse
 * @param data Datum
 */
void Maussensor::maus_sens_write(int8 adr, uint8 data){
	int16 i;
	
	//MOUSE_Enable();
	
	maus_sens_writeByte(adr|=0x80);  //rl MSB muss 1 sein Datenblatt S.12 Write Operation
	maus_sens_writeByte(data);
	for (i=0; i<300; i++){ asm volatile("nop"); 	}	// mindestens 100 Mikrosekunden Pause!!!
}

/*!
 * Schickt ein Lesekommando an den Sensor
 * und liest ein Byte zurueck
 * @param adr die Adresse
 * @return das Datum
 */
uint8 Maussensor::maus_sens_read(uint8 adr){
	//MOUSE_Enable();
	int16 i;
	maus_sens_writeByte(adr);
	for (i=0; i<300; i++){asm volatile("nop");}	// mindestens 100 Mikrosekunden Pause!!!
	
	return maus_sens_readByte();
}

/*! 
 * Initialisiere Maussensor
 */ 
void Maussensor::maus_sens_init(void){
	msleep(100);
	
	MAUS_DDR  |= (1<<sck_pin); 	// SCK auf Output
	MAUS_PORT &= ~(1<<sck_pin);	// SCK auf 0
	
	msleep(10);
	
	maus_sens_write(MOUSE_CONFIG_REG,MOUSE_CFG_RESET);	//Reset sensor
	maus_sens_write(MOUSE_CONFIG_REG,MOUSE_CFG_FORCEAWAKE);	//Always on
}

/*! muessen wir nach dem ersten Pixel suchen?*/
static uint8 firstRead;
/*!
 * Bereitet das auslesen eines ganzen Bildes vor
 */
void Maussensor::maus_image_prepare(void){
	maus_sens_write(MOUSE_CONFIG_REG,MOUSE_CFG_FORCEAWAKE);	//Always on

	maus_sens_write(MOUSE_PIXEL_DATA_REG,0x00);	// Frame grabben anstossen
	firstRead=1; //suche erstes Pixel 
}

/*!
 * Liefert bei jedem Aufruf das naechste Pixel des Bildes
 * Insgesamt gibt es 324 Pixel
 * <pre>
 * 18 36 ... 324
 * .. .. ... ..
 *  2 20 ... ..
 *  1 19 ... 307
 * </pre>
 * Bevor diese Funktion aufgerufen wird, muss maus_image_prepare() aufgerufen werden!
 * @return Die Pixeldaten (Bit 0 bis Bit5), Pruefbit, ob Daten gueltig (Bit6), Markierung fuer den Anfang eines Frames (Bit7)
 */
int8 Maussensor::maus_image_read(void){
	int8 pixel=maus_sens_read(MOUSE_PIXEL_DATA_REG);
	if ( firstRead ==1){
		while ( (pixel & 0x80) != 0x80){
			pixel=maus_sens_read(MOUSE_PIXEL_DATA_REG);
//			if ((pixel & 0x70) != 0x70)
//				return 0;
		}
		firstRead=0;
	}
	
	return pixel;
}




