
/*
 * sensor.c
 *
 * Interfacing routines for the Sensirion SHT11 Temperature & Humidity sensor
 *
 *  Written by Daan Vreeken
 *   Danovitsch@hotmail.com
 *   (or Danovitsch@Danovitsch.dnsq.org)
 *
 *  Published under the terms of the GNU Public License 2.0
 *  (or any later version)
 */


#include <stdio.h>
#include <unistd.h>
#include <err.h>



#define DeviceTimeout		20
#define ReadTimeout		200



void outp(unsigned short Port, unsigned char Data)
{
	unsigned char	D = Data;
	
	__asm __volatile("outb %0,%%dx" : : "a" (D), "d" (Port) );
}

unsigned char inp(unsigned short Port)
{
	unsigned char   Data = 0;
	
	__asm __volatile("inb %%dx,%0" : "=a" (Data) : "d" (Port) );

	return Data;
}


//pin 14 : out: bit 2 of 0x27a
//pin 15 : in: bit 8 of 0x279
//pin 16 : out: bit 4 of 0x27a

int Data(int Level) {
	outp(0x27a,(inp(0x27a)&4) + 2*(!Level));
	usleep(1*1000);
	
	return (inp(0x279)&8)==8;
}

void Clock(int Level) {
	outp(0x27a,(inp(0x27a)&2) + 4*Level);
	usleep(1*1000);
}



void Bus_Init(void) {
	int		Cnt;
	
	//Initiate bus
	outp(0x278,0xff);
	Data(1);
	Clock(1);
	
	//Connection reset sequence
	for (Cnt=0; Cnt<9; Cnt++) {
		Clock(0);
		Clock(1);
	}
}



int Bus_Read(unsigned char Command) {
	int		Cnt;
	int		Time;
	int		ReadData;
	
	
	//Transmission start
	Clock(1);
	Data(0);
	Clock(0);
	Clock(1);
	Data(1);
	Clock(0);

	
	//Send address & command
	for (Cnt=0; Cnt<8; Cnt++) {
		if (((Command >> (7-Cnt))&1)==1)
			Data(1);
		else
			Data(0);

		Clock(1);
		Clock(0);
	}

	
	//ACK
	Data(1);
	Clock(1);
	
	Time=0;
	while ((Data(1)==1) && (Time++<DeviceTimeout))
		usleep(1*1000);
	if (Time>DeviceTimeout)
		printf("Device timed out!!!%c\n",0x07);

	Clock(0);


	//Wait for the SHT11 to get it's data ready
	Time=0;
	while ((Data(1)==1) && (Time++<ReadTimeout))
		usleep(1*1000);
	if (Time>ReadTimeout)
		printf("Measurement timed out!!!%c\n",0x07);
		

	//Now clock 2 bytes of data in...
	ReadData=0;
	
	for (Cnt=0; Cnt<8; Cnt++) {
		Clock(1);

		ReadData<<=1;
		if (Data(1)==1)
			ReadData|=1;
		
		Clock(0);
	}
	//ACK
	Data(0);
	Clock(1);
	Clock(0);
	Data(1);

	for (Cnt=0; Cnt<8; Cnt++) {
		Clock(1);

		ReadData<<=1;
		if (Data(1)==1)
			ReadData|=1;
		
		Clock(0);
	}
	//!ACK
	Data(1);
	Clock(1);
	Clock(0);
	
	return ReadData;
}



#define Cmd_ReadTemp		0x03
#define Cmd_ReadHum		0x05




int main(int argc, char *argv[])
{
	FILE		*IO = fopen("/dev/io","r");
	
	int		TempData;
	int		HumData;

	float		Temp;
	float		Humidity;
	

	if (IO==NULL) {
		err(1,"could not open /dev/io");
	}


	Bus_Init();

	TempData=Bus_Read(Cmd_ReadTemp);
	HumData=Bus_Read(Cmd_ReadHum);
		
	Temp=TempData*0.01-40.0;
	Humidity=-4.0 + 0.0405*HumData - 2.8*HumData*HumData/1000000;
		
	printf("temp: %.2f  hum: %.2f\n",Temp,Humidity);

	fclose(IO);
	
	
	return 0;
}







