/****
 printtemp.c by Andrew Huang <bunnie@mit.edu>
 ****/

#include <asm/io.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>

#define IS ==
#define AINT !=
#define AND &&
#define OR ||

/* offset of card */
#define CARD		0x300

/* 8255 defines -- address space of card */
#define A_PORT_A	0x00
#define A_PORT_B	0x01
#define A_PORT_C	0x02
#define A_CONTROL	0x03

#define B_PORT_A	0x04
#define B_PORT_B	0x05
#define B_PORT_C	0x06
#define B_CONTROL	0x07

/* bit masks */
#define PORT_C_LO_IOCTL	        0x01
#define PORT_B_IOCTL		0x02
#define	MODE_SELECT_B		0x04
#define	PORT_C_HI_IOCTL	        0x08
#define PORT_A_IOCTL		0x10
#define	MODE_SELECT_A		0x60 /* two bits */
#define	MODE_SET_FLAG		0x80 /* refers to same bit -- see data sheet */
#define BIT_SR_FLAG			0x00

/* bit values */
#define IOCTL_IN			0xFF
#define IOCTL_OUT			0x00
#define MODE0				0x0
#define MODE1				0x1
#define MODE2				0x2

#define SET_BIT				0xFF
#define RESET_BIT			0x00
#define BIT0				0x0
#define BIT1				0x1
#define BIT2				0x2
#define BIT3				0x3
#define BIT4				0x4
#define BIT5				0x5
#define BIT6				0x6
#define BIT7				0x7

/* ADC0809 bit masks */
/* PPI A */
#define CHAN				0x07 /* pass a value from 0-7 */
#define	ALE				0x08
#define	START				0x10
#define OE				0x20

/* PPI B */
#define EOC				0x01

#define NUMAVE        16

#define LOGNAME      "/var/adm/templog"

int gettemp(float *inside, float *outside)
{ /* gettemp */
  /* locals */
  int	 value;
  int    i;

  /* body */
  ioperm((unsigned long) CARD, (unsigned long) 0x10, 0x1 );

  /* initialize the card */
  /* note that power up state is as follows: */
  /* MODE 0: Basic Input/Outbut; Ports A, B, C are configured as input ports */
	
  /* configure for: Port C all outbuts, Ports A & B all inputs, Mode 0 for groups A and B */
  outb( (unsigned short) ((PORT_C_LO_IOCTL & IOCTL_OUT) | (PORT_B_IOCTL & IOCTL_IN) | \
	      (MODE_SELECT_B & MODE0) | (PORT_C_HI_IOCTL & IOCTL_OUT) | \
	      (PORT_A_IOCTL & IOCTL_IN) | (MODE_SELECT_A & MODE0) | \
	      (MODE_SET_FLAG) ),
              (unsigned short) (CARD | A_CONTROL) );

  for(i = 0, value = 0; i < NUMAVE; i++) {
    /* configure ADC0809 for channel 1 operation */	
    outb( ((CHAN & 1) ),(CARD | A_PORT_C) );  
    outb( ((CHAN & 1) | (ALE)),(CARD | A_PORT_C) );  
    outb( 0, (CARD | A_PORT_C) );
    
    /* start a conversion */
    outb(  START, (CARD | A_PORT_C) );
    outb(  0, (CARD | A_PORT_C) );
    
    /* wait for conversion to occur */
    usleep(200);    /* wait for 100 useconds */
    
    outb( OE, (CARD | A_PORT_C) );
    value += (int) inb( (CARD | A_PORT_A) );
    
    outb( (int) 0, (unsigned) (CARD | A_PORT_C) );
  } /* for */

  /*  printf("%d \n", (int) value / NUMAVE ); */
  *inside =  (float) ( ( (double)(value / NUMAVE) * 1.89 ) - 260);
  
  for(i = 0, value = 0; i < NUMAVE; i++) {
    /* configure ADC0809 for channel 2 operation */	
    outb( (int) ((CHAN & 2) ), (unsigned) (CARD | A_PORT_C) );  
    outb( (int) ((CHAN & 2) | (ALE)), (unsigned) (CARD | A_PORT_C) );  
    outb( (int) 0, (unsigned) (CARD | A_PORT_C) );
    
    /* start a conversion */
    outb( (int) START, (unsigned) (CARD | A_PORT_C) );
    outb( (int) 0, (unsigned) (CARD | A_PORT_C) );
    
    /* wait for conversion to occur */
    usleep(200);   /* wait for 100 useconds */
    
    outb( (int) OE, (unsigned) (CARD | A_PORT_C) );
    value += inb( (unsigned) (CARD | A_PORT_A) );
    /*  printf( "%d\n", value); */
    
    outb( (int) 0, (unsigned) (CARD | A_PORT_C) );
  } /* for */  

  /*  printf("%d \n", (int) value / NUMAVE ); */
  *outside = (float) ( ( (double)(value / NUMAVE) * 1.89 ) - 260);

  ioperm((unsigned long) CARD, (unsigned long) 0x08, 0x0 );
  
  return(1);

} /* end gettemp */


int main() {
  float inside, outside;

  gettemp(&inside, &outside);

  printf("Indoor temperature (near computer): %.0f F\n", inside );
  printf("Outdoor temperature: %.0f F\n", outside );

  exit(0);
}

