
/********************************
 *Testing D/A on a GESBC-9302
 *
 *******************************/

#include<unistd.h>
#include<sys/types.h>
#include<sys/mman.h>
#include<stdio.h>
#include<fcntl.h>
#include<assert.h>
#include<time.h>

/*Register addresses */ 
#define CHIP_SELECT_PAGE 0x80840000UL
#define SSP_PAGE         0x808A0000UL
#define SYSTEM_CTRL_PAGE 0x80930000UL

/*Offsets*/
#define SSPCR1           0x04
#define SSPCPSR          0x10
#define SSP_DATA         0x08
#define CHIP_SELECT_DATA 0x40	/* Port H Data Register */
#define CHIP_SELECT_DDR  0x44	/* Port H Data Direction Register */
#define DEVICE_CONFIG    0x80	/* Device Config Register */

#define TRUE  0
#define FALSE !TRUE

static inline unsigned short READP16(unsigned long addr) {
        unsigned short ret;

        asm volatile (
                "ldrh %0, [ %1 ]\n"
                : "=r" (ret)
                : "r" (addr)
                : "memory"
        );
        return ret;
}

static inline void WRITEP16(unsigned long addr, unsigned short dat) {
        asm volatile (
                "strh %1, [ %0 ]\n"
                :
                : "r" (addr), "r" (dat)
                : "memory"
        );
}

static inline unsigned long READP32(unsigned long addr) {
        unsigned long ret;

        asm volatile (
                "ldr %0, [ %1 ]\n"
                : "=r" (ret)
                : "r" (addr)
                : "memory"
        );
        return ret;
}

static inline void WRITEP32(unsigned long addr, unsigned long dat) {
        asm volatile (
                "str %1, [ %0 ]\n"
                :
                : "r" (addr), "r" (dat)
                : "memory"
        );
}


static inline unsigned char READP8(unsigned long addr) {
        unsigned char ret;

        asm volatile (
                "ldrb %0, [ %1 ]\n"
                : "=r" (ret)
                : "r" (addr)
                : "memory"
        );
        return ret;
}

static inline void WRITEP8(unsigned long addr, unsigned char dat) {
        asm volatile (
                "strb %1, [ %0 ]\n"
                :
                : "r" (addr), "r" (dat)
                : "memory"
        );
}
int main(int argc, char **argv) 
{
	unsigned long deviceCFG;
	double temp;
	volatile unsigned char *chip_select_page, *ssp_page, *sysctrl_page;
	unsigned char isNegative = FALSE;
	unsigned char portHDDR, portHDR;
	int i;
	
	int fd = open("/dev/mem", O_RDWR);
	assert(fd != -1);
	
	/* this program has 2 seconds to complete or it will be killed */
	alarm(2);

	/* Intialize our pointers */
	chip_select_page = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, CHIP_SELECT_PAGE);
	assert(chip_select_page != MAP_FAILED);
	sysctrl_page = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, SYSTEM_CTRL_PAGE);
	assert(sysctrl_page != MAP_FAILED);

	//make sure Port H is configured as GPIO (Not well documented by EP9302 user gudie
	// see EP9315 user gudie page 157,804 for port H function)
	for(i=0; i<10; i++)
	{
		deviceCFG=READP32( (unsigned long)(sysctrl_page + DEVICE_CONFIG) ); 
		if( (deviceCFG & 0x00000800ul) > 0)
			break;
		deviceCFG|=0x00000800ul;
		outl(0xAA, sysctrl_page+0xC0ul);
		outl(deviceCFG, sysctrl_page+DEVICE_CONFIG);
		usleep(100);
	}
	assert(i<10);

	ssp_page = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, SSP_PAGE);
	assert(ssp_page != MAP_FAILED);

	/* 
	 The EP93XX Users Manual says the following algorithm must 
	 be used to configure and enable the SPI bus
	 http://www-s.ti.com/sc/ds/tmp124.pdf
	*/

	/* 1.)	Set enable bit(SSE) in register SSPCR1*/
	WRITEP32( (unsigned long)(ssp_page + SSPCR1), 0x10 );
	
	/* 2.)	Write other SSP config registers(SSPCR0 & SSPCPSR)*/
	WRITEP32( (unsigned long)ssp_page, 0x4F ); 
	WRITEP32( (unsigned long)(ssp_page + SSPCPSR), 0xFE ); 

	/* 3.)	Clear the enable bit(SSE) in register SSPCR1*/
	WRITEP32( (unsigned long)(ssp_page + SSPCR1), 0x00 ); 
	//usleep(10000); //let the lines settle
	
	/* 4.)	Set the enable bit(SSE) in register SSPCR1*/
	WRITEP32( (unsigned long)(ssp_page + SSPCR1), 0x10 ); 

	/* Done with configuration now lets write to D/A */

	//enable the chip select, GPIO4 (Port H D2)
	portHDDR=READP8( (unsigned long)(chip_select_page + CHIP_SELECT_DDR) ); 
	WRITEP32( (unsigned long)(chip_select_page + CHIP_SELECT_DDR), 0x04 | portHDDR); 

	//write D/A channel 1
	portHDR=READP8( (unsigned long)(chip_select_page + CHIP_SELECT_DATA) ); 
	WRITEP32( (unsigned long)(chip_select_page + CHIP_SELECT_DATA), 0xFB & portHDR ); 
	portHDR=READP8( (unsigned long)(chip_select_page + CHIP_SELECT_DATA) ); 
	WRITEP32( (unsigned long)(ssp_page + SSP_DATA), 0x8400 ); /* ch1 = 1.25V */
	usleep(1000);	

	//bring D/A chip select up
	portHDR=READP8( (unsigned long)(chip_select_page + CHIP_SELECT_DATA) ); 
	WRITEP32( (unsigned long)(chip_select_page + CHIP_SELECT_DATA), 0x04 | portHDR ); 
      usleep(1000);

	//write D/A channel 2
	portHDR=READP8( (unsigned long)(chip_select_page + CHIP_SELECT_DATA) ); 
	WRITEP32( (unsigned long)(chip_select_page + CHIP_SELECT_DATA), 0xFB & portHDR ); 
	WRITEP32( (unsigned long)(ssp_page + SSP_DATA), 0x9800 ); /* ch2 = 2.50V */
	usleep(1000);	
	//bring D/A chip select up
	portHDR=READP8( (unsigned long)(chip_select_page + CHIP_SELECT_DATA) ); 
	WRITEP32( (unsigned long)(chip_select_page + CHIP_SELECT_DATA), 0x04 | portHDR ); 
      usleep(1000);

	//write D/A channel 3
	portHDR=READP8( (unsigned long)(chip_select_page + CHIP_SELECT_DATA) ); 
	WRITEP32( (unsigned long)(chip_select_page + CHIP_SELECT_DATA), 0xFB & portHDR ); 
	WRITEP32( (unsigned long)(ssp_page + SSP_DATA), 0xaC00 ); /* ch3 = 3.75V */
	usleep(1000);	
	//bring D/A chip select up
	portHDR=READP8( (unsigned long)(chip_select_page + CHIP_SELECT_DATA) ); 
	WRITEP32( (unsigned long)(chip_select_page + CHIP_SELECT_DATA), 0x04 | portHDR ); 
      usleep(1000);

	//write D/A channel 4
	portHDR=READP8( (unsigned long)(chip_select_page + CHIP_SELECT_DATA) ); 
	WRITEP32( (unsigned long)(chip_select_page + CHIP_SELECT_DATA), 0xFB & portHDR ); 
	WRITEP32( (unsigned long)(ssp_page + SSP_DATA), 0xbFFF ); /* ch4 = 5.00V */
	usleep(1000);	
	portHDR=READP8( (unsigned long)(chip_select_page + CHIP_SELECT_DATA) ); 
	WRITEP32( (unsigned long)(chip_select_page + CHIP_SELECT_DATA), 0x04 | portHDR ); 
      usleep(1000);

	//disable chip select
	portHDDR=READP8( (unsigned long)(chip_select_page + CHIP_SELECT_DDR) ); 
	WRITEP32( (unsigned long)(chip_select_page + CHIP_SELECT_DDR), 0xFB & portHDDR ); 
      
	printf("Data sent to D/A. ch1 = 1.25V, ch2 = 2.50V, ch3 = 3.75V, ch4 = 5.00V\n");
	return 0;
	
}

