#include <stdio.h>
#include <sys/io.h>
#include <unistd.h>

//#define	__DEBUG__

#define PARPORT_BASE	0x378
#define PARPORT_DATA	(PARPORT_BASE+0)	/*	Read/Write (bidir port) */
#define PARPORT_STATUS	(PARPORT_BASE+1)	/*	Read only		*/
#define PARPORT_CONTROL	(PARPORT_BASE+2)	/*	Write only		*/

#define PARPORT_CONTROL_BIDIR		0x20	/*	Bidirectional control (1=read from port)        */
#define PARPORT_CONTROL_IRQ		0x10	/*	Interrupt control (0=disable, 1=enable)         */
#define PARPORT_CONTROL_SELECT		0x08	/*	Select          pin 17, 1=low, 0=high           */
#define PARPORT_CONTROL_INIT		0x04	/*	Initialize      pin 16, 1=high, 0=low           */
#define PARPORT_CONTROL_AUTOFEED	0x02	/*	Auto Feed       pin 14, 1=low, 0=high           */
#define PARPORT_CONTROL_STROBE		0x01	/*	Strobe          pin 01, 1=low, 0=high           */


void	binaryDump(unsigned char byte);
void	fbinaryDump(FILE*,unsigned char byte);

void	i2cDelay(void);
void	i2cInit(int port);
void	i2cStart(int port);
void	i2cStop(int port);
void	i2cSendAck(int port);
void	i2cSendNAck(int port);
int	i2cSendByte(int port,unsigned char byte);
int	i2cRecvByte(int port);


void binaryDump(unsigned char byte)
{
	int	i;

	for(i=7;i>=0;i--)
		putchar((byte&(1<<i))?'1':'0');

	putchar('\n');
}

void fbinaryDump(FILE *f,unsigned char byte)
{
	int	i;

	for(i=7;i>=0;i--)
		fprintf(f,"%c",(byte&(1<<i))?'1':'0');
}


void i2cDelay(void)
{
	int	i;

	for(i=0;i<500000;i++);
}


void i2cInit(int port)
{
#ifdef	__DEBUG__
	printf("i2cInit()\tSCL=1\tSDA=1\n");
#endif

	/* SCL=SDA=1 */
	outb(0,port+2);
}


void i2cStart(int port)
{
#ifdef	__DEBUG__
	printf("i2cStart()\tSDA=0\tSCL=1\n");
#endif

	/* SDA=0,SCL=1 */
	outb(1,port+2);
	i2cDelay();

#ifdef	__DEBUG__
	printf("i2cStart()\tSDA=0\tSCL=0\n");
#endif

	/* SDA=SCL=0 */
	outb(3,port+2);
	i2cDelay();
}


void i2cStop(int port)
{
#ifdef	__DEBUG__
	printf("i2cStop()\tSDA=0\tSCL=0\n");
#endif

	/* SDA=0,SCL=0 */
	outb(3,port+2);
	i2cDelay();

#ifdef	__DEBUG__
	printf("i2cStop()\tSDA=0\tSCL=1\n");
#endif

	/* SDA=0,SCL=1 */
	outb(1,port+2);
	i2cDelay();

#ifdef	__DEBUG__
	printf("i2cStop()\tSDA=1\tSCL=1\n");
#endif

	/* SDA=1,SCL=1 */
	outb(0,port+2);
	i2cDelay();
}


void i2cSendAck(int port)
{
#ifdef	__DEBUG__
	printf("i2cSendAck()\tSDA=0\tSCL=0\n");
#endif

	/* SDA=0,SCL=0 */
	outb(3,port+2);
	i2cDelay();

#ifdef	__DEBUG__
	printf("i2cSendAck()\tSDA=0\tSCL=1\n");
#endif

	/* SDA=0,SCL=1 */
	outb(1,port+2);
	i2cDelay();

#ifdef	__DEBUG__
	printf("i2cSendAck()\tSDA=0\tSCL=0\n");
#endif

	/* SDA=0,SCL=0 */
	outb(3,port+2);
	i2cDelay();
}


void i2cSendNAck(int port)
{
#ifdef	__DEBUG__
	printf("i2cSendNAck()\tSDA=1\tSCL=0\n");
#endif

	/* SDA=0,SCL=0 */
	outb(2,port+2);
	i2cDelay();

#ifdef	__DEBUG__
	printf("i2cSendNAck()\tSDA=1\tSCL=1\n");
#endif

	/* SDA=0,SCL=1 */
	outb(0,port+2);
	i2cDelay();

#ifdef	__DEBUG__
	printf("i2cSendNAck()\tSDA=1\tSCL=0\n");
#endif

	/* SDA=0,SCL=0 */
	outb(2,port+2);
	i2cDelay();
}


/*	Sends a byte over the I2C bus
	Returns -1 if ACK, 0 if NACK from the slave I2C device
*/
int i2cSendByte(int port,unsigned char byte)
{
	int	i,p;


	for(i=7;i>=0;i--)
	{
#ifdef	__DEBUG__
		printf("i2cSendByte()\tSending %d\n",(byte>>i)&0x01);
#endif

		p=((byte>>i)&0x01?2:3);

		outb(p,port+2);
		i2cDelay();
		outb(p-2,port+2);
		i2cDelay();
		outb(p,port+2);
		i2cDelay();
	}

#ifdef	__DEBUG__
	printf("i2cSendByte()\tAwaiting for ACK\n");
#endif

	/* SCL=0,SDA=1 */
	outb(2,port+2);
	i2cDelay();

	/* SCL=SDA=1 */
	outb(0,port+2);
	i2cDelay();

	if(inb(port+1)&0x20)
		return 0;

	/* SCL=0,SDA=1 */
	outb(2,port+2);

	return -1;
}


int i2cRecvByte(int port)
{
	unsigned char	readByte,readBit;
	int		i;


#ifdef	__DEBUG__
	printf("i2cRecvByte()\tSDA=1\tSCL=0\n");
#endif

	/* SCL=0,SDA=1 */
	outb(2,port+2);
	i2cDelay();

	readByte=0;
	for(i=7;i>=0;i--)
	{
#ifdef	__DEBUG__
		printf("i2cRecvByte()\tGetting bit #%d\n",i);
#endif

		/* SCL=SDA=1 */
		outb(0,port+2);
		i2cDelay();

		readBit=(inb(port+1)&0x20)?1:0;

#ifdef	__DEBUG__
		printf("i2cRecvByte()\tGot %d\n",readBit);
#endif

		readByte|=readBit<<i;

		/* SCL=0,SDA=1 */
		outb(2,port+2);
		i2cDelay();
	}

#ifdef	__DEBUG__
	printf("Got Byte: ");binaryDump(readByte);
#endif

	return readByte;
}


int main(int argc,char **argv)
{
	char		dummy[128];
	unsigned int	MSByte,LSByte;
	float		temp;

        if(argc==2&&!strcmp(argv[1],"index"))
        {
                printf("000\n");
                return 0;
        }


	if(ioperm(PARPORT_BASE,3,1))
	{
		printf("ioperm() error\n");
		return -1;
	}

	i2cInit(PARPORT_BASE);

	/* Configuration register */

/*
	printf("--------- Configuration register ---------\n");

	i2cStart(PARPORT_BASE);

	if(i2cSendByte(PARPORT_BASE,0x90))
		printf("Got ACK!\n");
	else
		printf("Got NACK...\n");

	if(i2cSendByte(PARPORT_BASE,0xac))
		printf("Got ACK!\n");
	else
		printf("Got NACK...\n");
	
	if(i2cSendByte(PARPORT_BASE,0x00))
		printf("Got ACK!\n");
	else
		printf("Got NACK...\n");

	i2cStop(PARPORT_BASE);
*/
	/* Start Convert */

#ifdef	__DEBUG__
	printf("--------- Start Convert ---------\n");
#endif

	i2cStart(PARPORT_BASE);

	if(i2cSendByte(PARPORT_BASE,0x90))
	{
#ifdef	__DEBUG__
		printf("Got ACK!\n");
#endif
	}
	else
	{
#ifdef	__DEBUG__
		printf("Got NACK...\n");
#endif
	}
	
	if(i2cSendByte(PARPORT_BASE,0xee))
	{
#ifdef	__DEBUG__
		printf("Got ACK!\n");
#endif
	}
	else
	{
#ifdef	__DEBUG__
		printf("Got NACK...\n");
#endif
	}

	i2cStop(PARPORT_BASE);

	/* Read temperature */

#ifdef	__DEBUG__
	printf("--------- Read temperature ---------\n");
#endif

//	while(1)
//{
	sleep(2);

	i2cStart(PARPORT_BASE);

	if(i2cSendByte(PARPORT_BASE,0x90))
	{
#ifdef	__DEBUG__
		printf("Got ACK!\n");
#endif
	}
	else
	{
#ifdef	__DEBUG__
		printf("Got NACK...\n");
#endif
	}
	
	if(i2cSendByte(PARPORT_BASE,0xaa))
	{
#ifdef	__DEBUG__
		printf("Got ACK!\n");
#endif
	}
	else
	{
#ifdef	__DEBUG__
		printf("Got NACK...\n");
#endif
	}

	do
	{
		i2cStart(PARPORT_BASE);
		i2cDelay();

/*
	if(i2cSendByte(PARPORT_BASE,0x91))
		printf("Got ACK!\n");
	else
		printf("Got NACK...\n");
*/
	}
	while(!i2cSendByte(PARPORT_BASE,0x91));

	MSByte=i2cRecvByte(PARPORT_BASE);
#ifdef	__DEBUG__
	printf("MSByte: %.2x\n",MSByte);
	printf("MSByte:\t");binaryDump(MSByte);
	printf("MSByte<<3:\t");binaryDump(MSByte<<3);
#endif
	i2cSendAck(PARPORT_BASE);

	LSByte=i2cRecvByte(PARPORT_BASE);

#ifdef	__DEBUG__
	printf("LSByte: %.2x\n",LSByte);
	printf("LSByte: ");binaryDump(LSByte);
	printf("(LSByte>>3)&0x1f:\t");binaryDump((LSByte>>3)&0x1f);
#endif

	i2cSendNAck(PARPORT_BASE);


	unsigned char MSB,LSB;

	MSB=MSByte;
	LSB=LSByte;

	if(MSB>=128)
	{
		// Negative temperatures
		temp=-(( ( ((255-MSB)<<8)|((255-LSB)&0xf8)) +8) /8)*0.03125;
	}
	else
	{
		// Positive temperatures
		temp=(MSB<<8|LSB)/8*0.03125;
	}

	printf("%f\n",temp);

	i2cStop(PARPORT_BASE);

	// ----------------------------------
/*
	FILE *f;

	f=fopen("/tmp/ds1624.txt","a");
	fbinaryDump(f,MSB);
	fprintf(f," ");
	fbinaryDump(f,LSB);
	fprintf(f," ");
	fprintf(f,"%f\n",temp);
	fclose(f);
*/
	// ----------------------------------

	return 0;
}
