/*
 * CSenzor.c
 *
 * Created: 7.9.2013 14:53:31
 *  Author: daveport
 */ 

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>


#include "cfg.h"
#include "uart.h"
#include "uart_addon.h"
#include "onewire.h"
#include "ds18x20.h"
#include "eeprom_default.h"
#include "wizfi.h"

#define ERR_MORE_SENZORS 0xF0;

void measurement(void);
void sensor_init (void);
void uart_put_temp(int16_t decicelsius);
//void uart_put_ip(ipAdd_t ee_src);

static volatile uint8_t measP;
static volatile uint8_t	measT;
static volatile uint8_t measRqst = 0;
static volatile uint16_t measAge;

static int16_t decicelsius; //.. volatile?
static uint8_t sensorFamily;
static uint8_t sensorError = OW_PRESENCE_ERR; //2=zkrat, 3=no senzor, 255=po initu, když není senzor nebo je zkrat, 240=více senzorů

//---------------------------------------------------------

void measTcpHandler(uint8_t cid, ipAdd_t ip, char* data)
{
	/*printf("* measTcpHandler(%i, %i.%i.%i.%i, %s)\r\n",
	cid,
	ip[0],ip[1],ip[2],ip[3],
	data);
	*/
	if (wzf_startDataSend(cid) == WZF_ACK)
	{
		wzf_dataSend("Odpověď.");
		wzf_endDataSend();
	}
}

void broadcastHandler(uint8_t cid, ipAdd_t ip, char* data)
{
	/*
	printf("* broadcastHandler(%i, %i.%i.%i.%i, %s)\r\n",
	cid,
	ip[0],ip[1],ip[2],ip[3],
	data);*/
}

/*
void restart() __attribute__((noreturn))
{	
}/*

/************************************************************************/
/*                                                                      */
/************************************************************************/
__attribute__((OS_main)) int main(void) 
{

	DDRD |= (1 << PD7); // PD7 ako výstupný
	
	// preddelicka /1024 (128us)
	//TCCR0 |= (1 << CS02) | (1 << CS00);
	//TIMSK |= (1 << TOIE0); // prerušenie pri pretečení TCNT0	
	
	// inicializace sekundového čítače
	TCCR1B |= (1 << CS12) | (1 << CS10) | (1 << WGM12);
	TIMSK |= (1 << OCIE1A);
	TCNT1 = 0;
	OCR1A = F_CPU/1024;		// nastavení s předděličkou 1024 pro 1s

	// inicializace čítače požadavků na měření	
	measP = eeprom_read_byte(&EE_measPeriod);
	measT = measP;
	measRqst = 0;
	measAge = UINT16_MAX;
		
			
	//---------------------------------------------------------
	
	uint8_t  runsCt = eeprom_read_byte(&EE_runs);
	runsCt++;
	eeprom_write_byte(&EE_runs, runsCt);
	
	uart_puts_P (NEWLINESTR "% START ");
	uart_put_int((int)runsCt);
	uart_puts_P (NEWLINESTR);
	
	const ipAdd_t selfIp = {10,0,0,21};
	const ipAdd_t maskIp = {255,255,255,0};
	const ipAdd_t gateIp = {10,0,0,138};
	const char* ssid = "Lab";
	const char* psk = "dp126761";

	uint8_t measTcpServerCid = -1;
	uint8_t broadcastCid = -1;

	for (;;)
	{
		// úvodní inicializace

		wzf_setAT();
		
		if (wzf_setNetwork(selfIp, maskIp, gateIp, WZF_DHCP_ENABLE) != WZF_OK)
		break;

		if (wzf_setWLan(psk, WZF_INFRASTRUCTURE) != WZF_OK)
		break;

		for (;;)
		{

			// připojení k AP

			for (;;)
			{
				//.. zde možná lépe autoconnect (ATA)
				wzf_result_t r = wzf_associate(ssid);
				if (r == WZF_OK)
					break;			// připojeno, pokračovat
				if (r == WZF_TIMEOUT)
					goto RestartWizFi_l;
			}
			
			// nastavení serverů

			//ipAdd_t x; // = {10,1,1,20};
			//x[0] = 10U; x[1] = 1U; x[2] = 1U; x[3] = 20U;
			//wzf_openTCPClient(x, 5001, &measTcpHandler, &measTcpServerCid);
			
			if (wzf_openTCPServer(5000, &measTcpHandler, &measTcpServerCid) != WZF_OK)
				break;

			if (wzf_openUDPListener(6000, &broadcastHandler, &broadcastCid) != WZF_OK)
				break;

			for (;;)					// main loop
			{							
				//emulate();
				
				if (measRqst)
				{
					measurement();
					if (!sensorError)
					{
						uart_puts_P( NEWLINESTR "% T=");
						uart_put_temp(decicelsius);
					}
					else
					{
						uart_puts_P( NEWLINESTR "% E=");
						uart_put_int(sensorError);
						uart_puts_P( " A=");
						uart_put_int((int)measAge);
						sensor_init();
					}
					measRqst = 0; //.. má se mezi tím čítat nový interval nebo raději ne?
				}
						
				if (wzf_exec() == WZF_DISASSOCIATED)
					break;				// opakovat připojení k AP

				//.. Po určité době nekomunikace (komunikace nuluje počítadlo) se bude
				//   odesílat alespoň AT<CR>, aby se ošetřil stav, kdyby modul zatuhnul.
				//   Minimálně na straně pasivně čekající na připojení (senzor).
			}
		}
		
		// po chybě komunikace s modulem
		RestartWizFi_l:
		if (wzf_reset() != WZF_RESET)		// pokus o sw reset
		{
			// pokud se nezdařil, pak hw reset
			//.. provedení hw restartu (napájením nebo přes pin)
		}

	}	
	
	
	
}

void measurement(void)
{
	if (sensorError)
		sensor_init();

	if (sensorError)
		return;
	
	sensorError = DS18X20_start_meas (DS18X20_POWER_EXTERN, NULL);	
	
	if (sensorError)
		return;
	
	while (DS18X20_conversion_in_progress()); //.. a co zásek?	
	
	sensorError = DS18X20_read_decicelsius_single (sensorFamily, &decicelsius);
	if (!sensorError)
		measAge = 0;
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
//static void meas(void)
//{
	//sensorError = DS18X20_start_meas (DS18X20_POWER_EXTERN, NULL);
	//
	//if (sensorError) return;
			//
	//while (DS18X20_conversion_in_progress()); //.. a co zásek?
		//
	//sensorError = DS18X20_read_decicelsius_single (sensorFamily, &decicelsius);
	//
//}

/************************************************************************/
/*                                                                      */
/************************************************************************/
void sensor_init (void)
{	
	uint8_t id[OW_ROMCODE_SIZE];

	ow_reset();
	sensorError = OW_SEARCH_FIRST;	
	
	DS18X20_find_sensor (&sensorError, &id[0]);

	if (!sensorError)		// nebo-li sensorError = OW_LAST_DEVICE
	{
		sensorFamily = id[0]; //	*family = id[0];
		return;
	}
	
    if (sensorError == OW_PRESENCE_ERR || sensorError == OW_DATA_ERR)
	{
		return;
	}
	sensorError = ERR_MORE_SENZORS;
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
void uart_put_temp(int16_t decicelsius)
{
	char s[10];

	DS18X20_format_from_decicelsius( decicelsius, s, 10 );
	uart_puts( s );
	uart_puts_P(" °C");
		
}

ISR (TIMER1_COMPA_vect)
{	
	if (measAge < UINT16_MAX)
		measAge++;
		
	measT--;
	if (!measT)
	{
		measT = measP;
		measRqst = 1;		// požadavek měření
	}
	wzf_tick();			//.. změnit na 1 nebo 10 ms
}

/*
ISR (TIMER0_OVF_vect){

	static uint8_t	measT;	//..incializovat? jak,kde
	measT--;
	if (!measT)
	{
		measT = 211;		// 11059200/1024/256/211 = 0.2 Hz
		measRqst = 1;		// požadavek měření
	}
}
*/



