/*
 ============================================================================
 Name        : kernel.c
 Author      : Ning, Guanghan
 Version     :
 Copyright   : University of Missouri
 Description : Hello World in C, Ansi-style
 ============================================================================
 */
#define MODULE
#define __KERNEL__

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/time.h>

#include <asm/io.h>
#include <rtai.h>
#include <rtai_sched.h>
#include <rtai_fifos.h>
#include <unistd.h>
#include <stdio.h>
//#include <semaphore.h>

MODULE_LICENSE("GPL");


RTIME period;           //check the button every 100ms.
static RT_TASK rttask;  // rttask to check the button and derive GPSdata

typedef struct GPSDATA
{
	int pressed;
}GPSdata;

char msg[1024];

static void RT_task_func(int t)
{
	int n;
	char buffer[1024];
	int fifo_read, fifo_write;
	GPSdata data_from_kernel;

	//------------------
	//Configure B0 button
	unsigned long *ptr;
	unsigned long *pdata;
	unsigned long *pddr;
	ptr = (unsigned long*)__ioremap(0x80840000,4096,0); //mapping
	pddr  =ptr + 5;										// point to data direction register
	pdata = ptr + 1;									// point to data register
	
	fifo_read= 0;
	fifo_write= 1;
	printk("RT task created. \n");
	while(1)
	{
		rt_task_wait_period();  //wait a period before executing next code
        //------------------check button--------------------------------
        n= *pdata- 126 +96;// -128;
		if( n!= 0)      //waiting for the button to be pressed
		{
			printk("n = %d\n", n);
			data_from_kernel.pressed= 1;
			rtf_put(fifo_write, &data_from_kernel.pressed, sizeof(data_from_kernel.pressed));
			n= 0;        //stop putting flag to user space through fifo
		}
	}

}

 int init_module(void)
{
	GPSdata data_from_kernel;
	int fifo_read, fifo_write;
	fifo_read= 0;                //0 symbolizes fifo_in
	fifo_write= 1;               //1 symbolizes fifo_out
	rt_set_periodic_mode();      //make it periodic mode

	printk("Initiate module!\n");
	//Button configuration
	//Configure B0 button
	unsigned long *ptr;
	unsigned long *pdata;
	unsigned long *pddr;
	ptr = (unsigned long*)__ioremap(0x80840000,4096,0); //mapping
	pddr  =ptr + 5;										// point to data direction register
	pdata = ptr + 1;									// point to data register
	*pddr  |= 0x01;										// set B0 as input
	*pdata &= 0x00;	                                    //set initial value 1
	//Create FIFO
	 rtf_create(fifo_read, 10*sizeof(msg));//fifo 0 read
     rtf_create(fifo_write, 10*sizeof(data_from_kernel));//fifo 1 write
     period = start_rt_timer(nano2count(1000000)); //100* 1ms =100ms

	//Create Tasks
	rt_task_init(&rttask, RT_task_func, 0, 256, 0, 0, 0);
	rt_task_make_periodic(&rttask, rt_get_time() + 100*period, 100*period);

	return 0;
}

 void cleanup_module(void)
{
	printk("Clean up module!!!!!\n");
	stop_rt_timer();
	rtf_destroy(0);         //destroy fifo_in
	rtf_destroy(1);         //destroy fifo_out
	rt_task_delete(&rttask);
}


