/*
 * prxk.c
 *
 *  Created on: May 6, 2014
 *      Author: kab8c8
 *      prxk.c means project Receiving Kernel Program
 */
#ifndef MODULE
#define MODULE
#endif
#ifndef __KERNEL__
#define __KERNEL__
#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <rtai.h>
#include <rtai_sched.h>	// scheduler
#include <rtai_fifos.h>	// for FIFOs
#include <linux/time.h>
MODULE_LICENSE("GPL");
unsigned long *ptr; //Global holds pointer to mapped memory IO
unsigned long *pBdr; //Global port B data register
unsigned long *pBddr; //Global port B data Direction register
unsigned long *pFdr; //Global port F data register
unsigned long *pFddr; //Global port F Data Direction Register
static RT_TASK Rt_Task_Speaker_Forever;
static void Toggle_Speaker_Forever(int t) {
	*pBdr = *pBdr | 0x20;//Red led on which will be replaced by the relay output.
	printk("\n\nToggle_Speaker_Forever Module Installed. Red LED Should be on\n"); //use dmesg command to read the log file.
	while (1) {
		//keep same distance from after rt wait and order of tasks to keep the periods between performing the tasks equal.
		rt_task_wait_period();
		*pFdr = *pFdr | 0x02; //"turn on" speaker
		//blocking function. wait for the period to occur.
		rt_task_wait_period();
		*pFdr = *pFdr & 0xFFFFFFFD; //"turn off" speaker
	}
}
int init_module(void) {
	printk("Installing project receiving side kernel\n");
	//remap I/O addresses to virtual memory addresses that the processor can access.
	ptr = (unsigned long *) __ioremap(0x80840000, 4096, 0);
	pBdr = (unsigned long *) ((char *) ptr + 0x04);//offsets to port B = 0x8084_0004
	pFdr = (unsigned long *) ((char *) ptr + 0x30);//offsets to port F = 0x8084_0030
	pBddr = (unsigned long *) ((char *) pBdr + 0x10); //offsets to DDR for port B = 0x8084_0014
	pFddr = (unsigned long *) ((char *) ptr + 0x34); //offsets to DDR for port F = 0x8084_0034
	//set data direction registers
	*pBddr = *pBddr | 0xE0;
	*pBddr = *pBddr & 0xFFFFFFE0;
	//set speaker port to output.
	*pFddr = *pFddr | 0x02; // 0000_0010 Set 2nd bit to 1 to output
	rt_set_periodic_mode(); // set periodic mode
	RTIME period = start_rt_timer(nano2count(100000));
	rt_task_init(&Rt_Task_Speaker_Forever, Toggle_Speaker_Forever, 0, 256, 0, 0, 0);
	rt_task_make_periodic(&Rt_Task_Speaker_Forever, rt_get_time(), period * 7);
	return 0;
}
void cleanup_module(void) {
	printk("Removing project receiving side kernel");
	*pBdr = *pBdr & 0xFFFFFFDF; //turn off red LED/output
	rt_task_delete(&Rt_Task_Speaker_Forever); //delete realtime task
	stop_rt_timer(); //stop timer
}
