//Only for LP-8x21 and LP-9x21
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>

#define LP8x21 1

#define MRAM_BASE_ADDR   0x100A000
#define SWITCH_BASE_ADDR 0x1009000
#define MRAM_MAP_SIZE    4096UL
#define MRAM_MAP_MASK    (MRAM_MAP_SIZE - 1)

#define MRAM_SIZE        0x20000 //128 KB = 64(pages) x 2048(bytes)

int main(int argc, char **argv) 
{
	unsigned int ii;
	void *map_base, *switch_base, *virt_addr;
 	unsigned char buf[64], rbuf[64]; 
	off_t addr=0;
	int size=16;
	int mmap_fd = -1;
	int mmap_fd2 = -1;
	unsigned int page = 0;	//2^8 = 256 = 0 ~ 255
	unsigned char wdata = 1, rdata = 0;

	printf("LP-8x21 MRAM Test\n");

	mmap_fd = open("/dev/mem", O_RDWR | O_SYNC);
	if (mmap_fd < 0) 
		return -1;
  
	/* Map one page */
	map_base = mmap(0, MRAM_MAP_SIZE , PROT_READ | PROT_WRITE, MAP_SHARED, mmap_fd, MRAM_BASE_ADDR & ~MRAM_MAP_MASK);

	if(map_base == (void *) -1) 
		return -1;

	mmap_fd2 = open("/dev/mem", O_RDWR | O_SYNC);
	if (mmap_fd2 < 0) 
		return -1;

	switch_base = mmap(0, MRAM_MAP_SIZE , PROT_READ | PROT_WRITE, MAP_SHARED, mmap_fd2, SWITCH_BASE_ADDR & ~MRAM_MAP_MASK);

	if(switch_base == (void *) -1) 
		return -1;

	printf("Memory mapped at virt_addr %p, phy_addr %p\n", map_base, addr); //debug only
	printf("MRAM Page 0 ~ 63 write ... ");

	for(page = 0; page < 64; page++)
	{
		/* Switch page */
		virt_addr = switch_base + 0x1e;  //0x100901E
		*((unsigned char *) virt_addr) = page; 
    
		/* Write data */
		virt_addr = map_base + addr;   //0x100A000

		for(ii=0; ii<2048; ii++) //Page N(0x100A000 ~ 0x100A7ff)
		{
			*((unsigned char *) (virt_addr+(ii<<1))) = wdata; 
			(wdata == 0x80) ? (wdata = 1) : (wdata <<= 1);
		}
	}

	printf("over ... wait 1 secs\n");

	sleep(1);


	wdata = 1;

	printf("MRAM Page 0 ~ 63 read and check ... ");

	for(page = 0; page < 64; page++)
	{
                /* Switch page */
		virt_addr = switch_base + 0x1e;  //0x100901E
		*((unsigned char *) virt_addr) = page;

		/* Read data */
		virt_addr = map_base + addr;   //Page N(0x100A000 ~ 0x100A7ff)

		for(ii=0; ii<2048; ii++)
		{
			rdata = *((unsigned char *) (virt_addr+(ii<<1)));

			if(rdata != wdata)
				printf("Page %d -- wdta(0x%02x) != rdata(0x%02x)\n", page, wdata, rdata);
			else
				printf("Page %d -- wdta(0x%02x) = rdata(0x%02x)\n", page, wdata, rdata);
			(wdata == 0x80) ? (wdata = 1) : (wdata <<= 1);
		}
  	}

	printf("over\n");

	/* Unmap */
	if(munmap(map_base, MRAM_MAP_SIZE) == -1)  
		return -1;

	if(munmap(switch_base, MRAM_MAP_SIZE) == -1)  
		return -1;

	return 0;
}
