#include <linux/errno.h>
#include <rtl.h>
#include <time.h>

#include <rtl_sched.h>
#include <rtl_fifo.h>

#include <pthread.h>
#include <mbuff.h>
#include <math.h>

#include "adc.h"
#include "period.h"

pthread_t mytask;

volatile float * data;
volatile struct my_msg_struct * msg;

void *thread_code(void *arg)
{
	hrtime_t s_time;
	float t, t0;
	int count, count_record, flag = 0;

	int i, j;

	while(1){
		int ret;
		int err;

		ret = pthread_wait_np();

		if (msg->command == START_TASK) {
			msg->command = STOP_TASK;
			flag = 1;

			count = 0;
			count_record = 0;
			s_time = gethrtime();
			t0 = 0;
			pthread_make_periodic_np(pthread_self(), s_time, SAMPLING_PERIOD * 1.0e9);
		}

		if(flag == 1){
			  
			t = (gethrtime() - s_time)*1.0e-9;

			count++;
			if(count == 2){
				da_conv(1.0, 0);
				count = 0;
			}else{
				da_conv(0, 0);
			}
			
			if(count_record < BUF_LEN * RECORDING_SAMPLES){
				data[count_record++] = t; // 現在時刻
				data[count_record++] = t - t0; // 前回からの差分
				t0 = t;
			}else{
				flag = 0;
				pthread_make_periodic_np(pthread_self(), gethrtime(), 0.1 * 1e9);
			}

		}

	}

       	return 0;
}

int
init_module(void)
{
	pthread_attr_t attr;
	struct sched_param sched_param;
	int ret;

	if((data = (volatile float *) mbuff_alloc("data", BUF_LEN * RECORDING_SAMPLES * sizeof(float))) == NULL){
		rtl_printf("mbuff_alloc failed for data\n");
		return -1;
	}

	if((msg = (volatile struct my_msg_struct *) mbuff_alloc("msg", sizeof(struct my_msg_struct))) == NULL){
		rtl_printf("mbuff_alloc failed\n");
		return -1;
	}
	msg->command = STOP_TASK;

	pthread_attr_init (&attr);       /* 属性の初期化 */
	pthread_attr_setfp_np(&attr, 1); /* FPU の使用を許可 */
	sched_param.sched_priority = 1;  /* 優先順位 */
	pthread_attr_setschedparam (&attr, &sched_param);

	ret = pthread_create (&mytask,  &attr, thread_code, (void *)0);
	pthread_make_periodic_np(mytask, gethrtime(), 0.1 * 1e9);

	init_dac();

	return 0;
}

void
cleanup_module(void)
{
	mbuff_free("data",(void*)data);
	mbuff_free("msg",(void*)msg);

	pthread_cancel(mytask);
	pthread_join(mytask, NULL);

	cleanup_dac();
}