#include "global.h"
#include <util/delay.h>
#include <avr/io.h>
#include "ledio.h"
#include "globals.h"
#include <avr/interrupt.h>
#include "rtc.h"
#include "uart2.h"
#include "rprintf.h"
#include "cmdline.h"
#include "cmds.h"
#include <stdlib.h>
#include <stdio.h>

/*
PD3: benne van-e a kártya
*/



/* Órajel leosztása
   proc. datasheet 135. oldal alapján */

//#define orajel_oszto (1<<CS12) | (1<<CS10) // 1024
//#define orajel_oszto (1<<CS12) // 256
#define orajel_oszto (1<<CS11) | (1<<CS10) // 64
//#define orajel_oszto (1<<CS11) // 8
//#define orajel_oszto (1<<CS10) // 1


//#define _faktor 979.9  // ezt az értéket akkor kaptam, mikor az 1 MHz-es órajelet 1024-gyel osztottam le
#define _faktor 15218.66 // hitelesítve ápr.19-én (64-es prescaler)



#define _max_puffer_meret 100

double puffer[_max_puffer_meret];

unsigned long int pido[100];
unsigned int hozadek=0; // ennyi*65536
int pidoi;

SIGNAL(SIG_INPUT_CAPTURE1) {
	pido[pidoi] = TCNT1+hozadek*65536;
	hozadek=0;
	pidoi++;
	TCNT1 = 0;
/*	if (pidoi%2) TCCR1B |= (1<<ICES1); else TCCR1B &= ~(1<<ICES1);*/
}

SIGNAL(SIG_OVERFLOW1) {
	hozadek++;
}

void init_timer(void) 
{
	PORTB = 0xff;
	DDRB = 0xff;

	cli(); 
	TCCR1A = 0;
	TCCR1B = orajel_oszto;
	TIMSK |= (1<<TICIE1) | (1<<TOIE1);
	DDRD = 32;
  
	pidoi = 0;		

	sei();
} 

void initRS232() {
	uartInit();
	uartSetBaudRate(0,_baudr); // cmdline
	rprintfInit(uart0SendByte);
	
	uartSetBaudRate(1,9600); // gprs
}

extern char filename[255];

void store(unsigned long int x, int *pufferi) {
	unsigned char RtcBuffer[6];
	unsigned char year, month, day, hours, minutes, seconds, hundredths;				

	if (*pufferi > _max_puffer_meret) rprintf("Túl kicsi a puffer: %d!\n",_max_puffer_meret);
	if (x) puffer[*pufferi] = _faktor/x; else puffer[*pufferi] = 0.0;
	if (streaming) {
		rprintf("Actual value (%d) (T=%d): ",*pufferi,x);
		rprintfFloat(6,puffer[*pufferi]);
		rprintfCRLF();
	}
	(*pufferi)++;
	if (*pufferi == tcs.puffer_tele) {
		int i;
		double osszegf,atlagf,minf,maxf,szorasf;
		*pufferi = 0;
		minf=puffer[0];
		maxf=puffer[0];
		osszegf=0.0;
		for (i=0; i < tcs.puffer_tele; i++) {
			if (puffer[i] < minf) minf = puffer[i];
			if (puffer[i] > maxf) maxf = puffer[i];			
			osszegf += puffer[i];
		}
	
		atlagf = osszegf / tcs.puffer_tele;

		szorasf = 0.0;		
		for (i=0; i < tcs.puffer_tele; i++) {
			szorasf += (puffer[i]-atlagf)*(puffer[i]-atlagf);
		}

		tcs.osszeg = (unsigned int)(osszegf); // ezt nem szorozzuk fel egyedül
		tcs.atlag = (unsigned int)(tcs.szorzo*atlagf);		
		tcs.szoras = (unsigned int)(tcs.szorzo*szorasf);		
		tcs.szorzo = 128;		
		tcs.minv = (unsigned int)(tcs.szorzo*minf);
		tcs.maxv = (unsigned int)(tcs.szorzo*maxf);

		debug_led_on();
		if(efs_init(&fs,0)!=0) {
			rprintf("Filesystem init error!\n");
			return;
		}
		
		if(file_fopen(&recordingfile,&fs.myFs, filename, MODE_APPEND)!=0) {
			rprintf("File opening error!\n");		
			return;
		}
	
		i2c_init();	
		GetRTC(RtcBuffer);
		
		file_write(&recordingfile, sizeof(RtcBuffer), (void*) &RtcBuffer);
		file_write(&recordingfile, sizeof(tcs), (void*) &tcs);

		debug_led_off();
		file_fclose(&recordingfile);
		fs_umount(&fs.myFs);
		PORTB = 0xff;
		DDRB = 0xff;	
		
		if (streaming) {
			decodeTime(RtcBuffer,&year,&month,&day,&hours,&minutes,&seconds,&hundredths);
			rprintf("Time: %d-%d-%d %d:%d:%d.%d",year,month,day,hours,minutes,seconds,hundredths);
			rprintfCRLF();

			rprintf("Sampling period: %d",tcs.sampling_period);rprintfCRLF();
			rprintf("Number of elements: %d",tcs.puffer_tele);rprintfCRLF();
			rprintf("Sum: %d",tcs.osszeg);rprintfCRLF();
			rprintf("Avg: %d",tcs.atlag);rprintfCRLF();
			rprintf("STD: %d",tcs.szoras);rprintfCRLF();
			rprintf("Scale: %d",tcs.szorzo);rprintfCRLF();
			rprintf("Min.val.: %d",tcs.minv);rprintfCRLF();
			rprintf("Max.val.: %d",tcs.maxv);rprintfCRLF();
		}
		*pufferi = 0;
	}
}

int nagyobb(const void *a, const void *b) {
	return (*(long int*)(a))-(*(long int*)(b));
}

void sum_and_store(int *pufferi) {
	unsigned int szamlalo = TCNT1;
	TCNT1 = 0;
	
	if (pidoi == 0) store(szamlalo+hozadek*65536,pufferi);
	else {
		unsigned long int median;
		qsort(pido, pidoi, sizeof(pido[0]), nagyobb);
		median = pido[pidoi/2];
		store(median,pufferi);
	}
}

void waitms(int t)
{
	int i;
	u08 c;
	PORTB &= ~(1<<6);	
	for (i=0; i <= t/10; i++) _delay_ms(10);
	PORTB |= (1<<6);
	while(uartReceiveByte(0,&c)) cmdlineInputFunc(c);
	cmdlineMainLoop();
} 

int main(void){
	int pufferi;
	init_globals();
	
	initRS232();
	rprintf("A meres elinditasahoz adja ki a start parancsot!\r\n");
	
	cmdlineInit();
	cmdlineSetOutputFunc(uart0SendByte);

	cmdlineAddCommand("help",		helpFunction);
	cmdlineAddCommand("gettime",	getTimeCommand);
	cmdlineAddCommand("settime",	setTimeCommand);
	cmdlineAddCommand("printsettings",	printSettings);	
	cmdlineAddCommand("ssp",	setSamplingPeriod);	
	
	cmdlineAddCommand("start",	start);
	cmdlineAddCommand("stop",	stop);	
	cmdlineAddCommand("dir",	dir);		
	cmdlineAddCommand("download",	download);
	
	cmdlineAddCommand("remove",	remove);
	
	cmdlineAddCommand("streaming",	streaming_on_off);

	cmdlineAddCommand("mmctest",	mmctest);
	
	// send a CR to cmdline input to stimulate a prompt
	cmdlineInputFunc('\r');

	pufferi = 0;
	
	waitms(5000);
	rprintf("start\r\n");
	start();
	
 	init_timer();
	
	while (1){
		waitms(tcs.sampling_period);
		if (merunk) sum_and_store(&pufferi);
//		init_timer();		
		pidoi = 0;		
	}

	return 0;
}
