
/********************************
 *Testing Digital I/O on a GESBC-9315
 *
 *******************************/

#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 DIGITAL_IO_PAGE  0x80840000UL
#define SYSTEM_CTRL_PAGE 0x80930000UL

/*Offsets*/
#define DEVICE_CONFIG   0x80	/* Device Config Register */
#define DIGITAL_IO_DATA 0x08	/* Port C Data Register */
#define DIGITAL_IO_DDR  0x18	/* Port C Data Direction 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) 
{
	volatile unsigned char *digital_io_page, *sysctrl_page;
	volatile unsigned char portCDDR, portCDR;
	volatile unsigned long deviceCFG;
	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 */
	digital_io_page = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, DIGITAL_IO_PAGE);
	assert(digital_io_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 C is configured as GPIO (EP9315 user gudie page 157,804)
	for(i=0; i<10; i++)
	{
		deviceCFG=READP32( (unsigned long)(sysctrl_page + DEVICE_CONFIG) ); 
		if( (deviceCFG & 0x08000000ul) > 0)
			break;
		deviceCFG|=0x08000000ul;
		outl(0xAA, sysctrl_page+0xC0ul);
		outl(deviceCFG, sysctrl_page+DEVICE_CONFIG);
		usleep(100);
	}
	assert(i<10);


	//enable the row 4 line (set it as output, on reset, all ports are default to input)
	portCDDR=READP8( (unsigned long)(digital_io_page + DIGITAL_IO_DDR) ); 
	WRITEP32( (unsigned long)(digital_io_page + DIGITAL_IO_DDR), 0x10 | portCDDR);

	//set the output low
	portCDR=READP8( (unsigned long)(digital_io_page + DIGITAL_IO_DATA) ); 
	WRITEP32( (unsigned long)(digital_io_page + DIGITAL_IO_DATA), 0xEF & portCDR ); 
      usleep(10000);
	//bring signal up
	portCDR=READP8( (unsigned long)(digital_io_page + DIGITAL_IO_DATA) ); 
	WRITEP32( (unsigned long)(digital_io_page + DIGITAL_IO_DATA), 0x10 | portCDR );

	return 0;
	
}
