/***************************************
*This program assumes a test fixture is 
*attached to the A/D header with 2.35 VDC
*on all even channels and 1.18 VDC on all
*odd channels. This test uses a 0-10V unipolar.
*Therefore even channels are nominally
*22% (21.5-22.5 => good) and odd channels are
*nominally 11% (10.5-11.5 => good).
***************************************/

#include<unistd.h>
#include<sys/types.h>
#include<sys/mman.h>
#include<stdio.h>
#include<fcntl.h>
#include<assert.h>
#include<time.h>
#include<stdlib.h>

#define PLD_ATOD_SET     0x01		//bit0 at OPTIONS
#define OPTIONS          0x22400000		
#define CTRL_BYTE        0x10f00000
#define BUSY             0x10800000
#define CHANNEL_0        0x50
#define CHANNEL_7        0x57
#define BUSYBIT          0x80

int main(int argc, char **argv) 
{
	volatile unsigned char *options, *controlByte, *busy;
	unsigned char *registerValue;
	unsigned short *results;
	double percentage;
	int ctrlByte, n;
	int fd = open("/dev/mem", O_RDWR|O_SYNC);
	assert(fd != -1);
		
	setvbuf(stdout, NULL, _IONBF, 0);

	/* Lets intialize our pointers */
	options = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd,
	  OPTIONS);
	assert(options != MAP_FAILED);
	controlByte = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED,
	  fd, CTRL_BYTE);
	assert(controlByte != MAP_FAILED);
	busy = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 
	  BUSY);
	assert(busy != MAP_FAILED);

	printf("checking if MAX197-ADC option is set...");
	registerValue = (unsigned char *)options;
	if( *registerValue & PLD_ATOD_SET ) {
		printf("ok\n"); 
	} else {
		printf("FAIL, not set\n");
		return 1;
	}

	/* Lets go do the conversions */
	for( ctrlByte = CHANNEL_0; ctrlByte <= CHANNEL_7; ctrlByte++)
	{
		//lets write out our control byte	
		*controlByte = ctrlByte;

		printf("waiting for ADC to respond on channel %d...",
		  ctrlByte - CHANNEL_0);
		//lets poll the busy bit to determine when the conversion is done
		registerValue = (unsigned char *)busy;

		n = 0; 
		while(n < 14 && (*registerValue & BUSYBIT) != 0x0) {
			usleep(1 << n);
			n++;
		}
		if (n == 14) {
			printf("FAIL, timed out\n");
			return 4;
		} else {
			printf("ok\n");
		}
	
		printf("reading result...");
		results = (unsigned short *) controlByte;	
		percentage = (((double) *results) * 100) / 4096;
	
		if( (ctrlByte - 0x10) % 2 ==0 ) //even number channel
		{
			if(percentage < 21.5 || percentage > 22.5) {
				printf("FAIL, got %3.1f%% "
				  "(should be 20%% - 24%%)\n", percentage);
				return 2;
			} else {
				printf("ok\n");
			}
		} else { //odd number channel
			if(percentage < 10.5 || percentage > 11.5) {
				printf("FAIL, got %3.1f%% "
				  "(should be 9%% - 13%%)\n", percentage);
				return 3;
			} else {
				printf("ok\n");
			}
		}
	}
	return 0;
}
