/**
 * \file
 *
 * \brief YARM Base application example
 *
 */
#include <port.h>
#include <stdbool.h>
#include <stdint.h>

#include <asf.h>

#include <serial.h>
#include <stdio_serial.h>
#include <sam0_usart/usart_serial.h>
#include "adc.h"

// From module: RTC - Real Time Counter in Count Mode (Callback APIs)
#include <rtc_count.h>
#include <rtc_count_interrupt.h>
#include <rtc_tamper.h>

#include "YARM_lib.h"
#include "BME280_lib.h"
#include "BMP180_lib.h"
#include "terminal_lib.h"
#include "LowPower_lib.h"

/* USART ********************************************************** */
#define CONF_STDIO_USART          SERCOM5	
#define CONF_STDIO_MUX_SETTING    USART_RX_1_TX_0_XCK_1
#define CONF_STDIO_PINMUX_PAD0    PINMUX_PA22D_SERCOM5_PAD0
#define CONF_STDIO_PINMUX_PAD1    PINMUX_PA23D_SERCOM5_PAD1
#define CONF_STDIO_PINMUX_PAD2    PINMUX_UNUSED
#define CONF_STDIO_PINMUX_PAD3    PINMUX_UNUSED
#define CONF_STDIO_BAUDRATE       115200

#define CONF_STDIO_PAD0_PIN PIN_PA22D_SERCOM5_PAD0
#define CONF_STDIO_PAD1_PIN PIN_PA23D_SERCOM5_PAD1

static struct usart_module usart_instance;
static void configure_usart(void);
/* /USART ********************************************************* */

/* RTC *****************************************/
void rtc_overflow_callback(void);
void configure_rtc_count(void);
void configure_rtc_callbacks(void);
struct rtc_module rtc_instance;
/* /RTC *****************************************/

/* YARM *****************************************/
uint32_t TX_ToYarmHarvest1( void);
uint32_t RX_FromYarmHarvest1( void);
uint32_t PrepareAckData( void);
/* /YARM *****************************************/


volatile uint32_t event_rtc;
uint32_t RSSI_Received;


typedef union
{
	uint8_t data[24];
	struct {
		uint32_t SerialNumber[4];
//		float t;
//		float p;
//		float h;
		uint32_t VoltageCommand;
		float rssi;
	} wval;
} SENSOR_DATA_t;

SENSOR_DATA_t sd;
#define SENSOR_DATA_LEN	(sizeof(SENSOR_DATA_t))

/* receive buffer used for all transactions */
#define BUF_LENGTH	64
static uint8_t rd_buffer[BUF_LENGTH];

int32_t	buffer_len;
float t, h, p;
float x, y, z;
char msg[64];

volatile uint32_t *ser_ptr1 = (volatile uint32_t *)0x0080A00C;
volatile uint32_t *ser_ptr2 = (volatile uint32_t *)0x0080A040;
uint8_t	serviceChannelReceived;
uint32_t rssiReceived;
uint32_t SerialNumber[4];
uint32_t counter_cycle;
uint32_t rxLength;
uint32_t txLength;

uint32_t txRepeat;
volatile uint32_t received_data;
//
uint32_t i, ii;
char waiting[]={'|','/','-','\\'};

void ChkConsoleOn( void);
volatile uint32_t ConsoleOn;

void ChkConsoleOn( void)
{
	struct port_config pin_conf;
	
	/* PA11 as ConsoleEnable */
	pin_conf.direction  = PORT_PIN_DIR_INPUT;
	pin_conf.input_pull = PORT_PIN_PULL_UP;
	port_pin_set_config(PIN_PA11, &pin_conf);
	
	ConsoleOn = !(port_pin_get_input_level(PIN_PA11));
}

#define ROBERTO_WAY		1

void rtc_overflow_callback(void)
{
	/* Do something on RTC overflow here */
	event_rtc=1;
}

void configure_rtc_count(void)
{
	struct rtc_count_config config_rtc_count;
	rtc_count_get_config_defaults(&config_rtc_count);
	config_rtc_count.prescaler           = RTC_COUNT_PRESCALER_DIV_1;
	config_rtc_count.mode                = RTC_COUNT_MODE_16BIT;
	//	#ifdef FEATURE_RTC_CONTINUOUSLY_UPDATED
	//	config_rtc_count.continuously_update = true;
	//	#endif
	rtc_count_init(&rtc_instance, RTC, &config_rtc_count);
	rtc_count_enable(&rtc_instance);
}

void configure_rtc_callbacks(void)
{
	rtc_count_register_callback( &rtc_instance, rtc_overflow_callback, RTC_COUNT_CALLBACK_OVERFLOW);
	rtc_count_enable_callback( &rtc_instance, RTC_COUNT_CALLBACK_OVERFLOW);
	event_rtc=0;
}

/**
 * \brief Configure usart.
 */
void configure_usart(void)
{
	struct usart_config config_usart;
	
	usart_get_config_defaults(&config_usart);
	config_usart.baudrate    = CONF_STDIO_BAUDRATE;
	config_usart.mux_setting = CONF_STDIO_MUX_SETTING;
	config_usart.pinmux_pad0 = CONF_STDIO_PINMUX_PAD0;
	config_usart.pinmux_pad1 = CONF_STDIO_PINMUX_PAD1;
	config_usart.pinmux_pad2 = CONF_STDIO_PINMUX_PAD2;
	config_usart.pinmux_pad3 = CONF_STDIO_PINMUX_PAD3;
	
	while (usart_init(&usart_instance, CONF_STDIO_USART, &config_usart) != STATUS_OK); 
	stdio_serial_init(&usart_instance, CONF_STDIO_USART, &config_usart);

	usart_enable(&usart_instance);
}


// ADC_POSITIVE_INPUT_PIN19
// ADC_POSITIVE_INPUT_PIN18
// ADC_POSITIVE_INPUT_PIN0
// ADC_POSITIVE_INPUT_PIN1

struct adc_module adc_instance;

#define VREF 3.35
float read_adc(int pin)
{
	struct adc_config config_adc;
	uint16_t result;

	adc_get_config_defaults(&config_adc);
	
	config_adc.clock_prescaler				= ADC_CLOCK_PRESCALER_DIV32;
	// Con ADC_REFCTRL_REFSEL_INTVCC2 la VREF è la VCC della YARM (3.35V)
	config_adc.reference					= ADC_REFCTRL_REFSEL_INTVCC2;
	config_adc.positive_input				= pin;
	config_adc.negative_input				= ADC_NEGATIVE_INPUT_GND;
	config_adc.resolution					= ADC_RESOLUTION_12BIT;
	config_adc.accumulate_samples			= ADC_ACCUMULATE_SAMPLES_1024;
	config_adc.divide_result				= ADC_DIVIDE_RESULT_16;
	
	adc_init(&adc_instance, ADC, &config_adc);
	adc_enable(&adc_instance);

	adc_start_conversion(&adc_instance);
	do {
		// Wait for conversion to be done and read out result
	}	while (adc_read(&adc_instance, &result) == STATUS_BUSY);
	adc_disable(&adc_instance);
	return (float)result*VREF/(float)4095;  
}



uint32_t RX_FromYarmHarvest1( void)
{
	uint8_t  service;
	uint8_t  channel;
	uint16_t rxLength;
    uint8_t  rxError;
	uint8_t *rd_buffer;	
	uint32_t	ii;
	
	// Loop waiting End of telegram
	if ( ConsoleOn) {
		TERM_TEXT_GREEN;
		printf("\r\n\r\n---- RX from YARM Harvest1 ------------------\r\n");
		TERM_TEXT_DEFAULT;
	}

	rxError = YARM_Receive (&rxLength, &rd_buffer, &service, &channel, &RSSI_Received);

	TERM_TEXT_GREEN;
	printf("Received %d bytes on service %d channel %d\r\n", rxLength, service, channel);

	if (ConsoleOn) {
		printf("Data Received [%d]\r\n", rxLength);
		for ( i=0; i<rxLength;i++)
		printf("0x%0X ", rd_buffer[i]);
		printf("\r\n");
		for ( i=0; i<rxLength;i++)
		printf("%c", (rd_buffer[i]>0x20 && rd_buffer[i]<0x7f)?rd_buffer[i]:'.');
		printf("\r\n");
	}

	// copy byte data on sensors data structure
	for ( ii=0; ii<SENSOR_DATA_LEN; ii++) {
		sd.data[ii]=rd_buffer[ii];
	}
	
	TERM_TEXT_GREEN;
	printf("Harvest1 ID: 0x%04X%04X%04X%04X\r\n",sd.wval.SerialNumber[0],
	sd.wval.SerialNumber[1],
	sd.wval.SerialNumber[2],
	sd.wval.SerialNumber[3]	);
#if 0	
	printf("temperature: %.2f\r\n",sd.wval.t);
	printf("pressure: %.2f\r\n", (sd.wval.p/100.0f));
	printf("humidity: %.2f\r\n", sd.wval.h);
#endif
	printf("Node Voltage: 0x%04x\r\n", sd.wval.VoltageCommand);
	printf("RSSI Received from Node: %.2f dBm\r\n", sd.wval.rssi);
	printf("RSSI: %.2f dBm\r\n", (RSSI_Received*1.0f/2.0f)-134.0f);
	printf("RxError: %d\r\n", rxError);
	printf("---- RX from YARM Harvest1 ------------------\r\n");
	TERM_TEXT_DEFAULT;
	return 0;
}

uint32_t PrepareAckData( void)
{
	uint32_t c;
	
	for ( c=0; c<SENSOR_DATA_LEN; c++) {
		sd.data[c]=0;
	}

	#if !ROBERTO_WAY
	BME280_Get_AllValues( &p, &t, &h);
	#else
	t=1.2f;
	p=(3.4f*100.0f);
	h=5.6f;
	delay_ms(10);
	#endif

	if ( 0 /*ConsoleOn*/) {
		TERM_TEXT_GREEN;
		printf("Temp:%.2f, Press: %.2f, Hum: %.2f\r\n", t, (p/100), h);
		TERM_TEXT_DEFAULT;
	}

	sd.wval.SerialNumber[0]=SerialNumber[0];
	sd.wval.SerialNumber[1]=SerialNumber[1];
	sd.wval.SerialNumber[2]=SerialNumber[2];
	sd.wval.SerialNumber[2]=SerialNumber[3];
	sd.wval.VoltageCommand = 2000;
	sd.wval.rssi=(float)((RSSI_Received*1.0f/2.0f)-134.0f);
	printf("Send to Node: Command = %d (%x); RSSI received from Node = %.02f\r\n", sd.wval.VoltageCommand, sd.wval.VoltageCommand, sd.wval.rssi);
//	sd.wval.p = p;
//	sd.wval.t = t;
//	sd.wval.h = h;
	/* MCU ID */

	sd.data[SENSOR_DATA_LEN+1]=checksum( &sd.data[0], SENSOR_DATA_LEN);
	
	return SENSOR_DATA_LEN+1;
}

uint32_t TX_ToYarmHarvest1( void)
{
	float alt=0.0f;
	uint32_t i;
	uint8_t  service = 3;
	uint8_t  channel = 0;
	uint8_t  power = 60;
	bool blocking = true;

	if ( ConsoleOn) {
		TERM_TEXT_GREEN;
		printf("\r\n\r\n---- Tx to YARM Harvest1 ------------------\r\n");
		TERM_TEXT_DEFAULT;
	}

	txLength = PrepareAckData();
	if (txLength==0)
	return 1;
	if ( ConsoleOn) {
		printf("Data to Send [%d]\r\n", txLength);
		for ( i=0; i<txLength;i++)
		printf(" 0x%0X, ", sd.data[i]);
		printf("\r\n");
	}
	YARM_Send (txLength, sd.data, service, channel, power, blocking);

	if ( ConsoleOn) {
		TERM_TEXT_GREEN;
		printf("---- Tx to YARM Harvest1 ------------------\r\n");
		TERM_TEXT_DEFAULT;
	}

	YARM_SetPollingMode();
	return 1;
}

void menuADC_Yarm(void) {
	printf("\n\r");
	printf("r) Read ADC\r\n");
	printf("\r\n");
}

void menuI2C_Yarm(void) {
	printf("\n\r");
	printf("r) Read BME280\r\n");
	printf("\r\n");
}


int main (void) {
	int c;
	ConsoleOn=1;
	system_init();
	/* BOD33 disabled */
	SUPC->BOD33.reg &= ~SUPC_BOD33_ENABLE;
	/* VDDCORE is supplied BUCK converter */
	SUPC->VREG.bit.SEL = SUPC_VREG_SEL_BUCK_Val;
	configure_usart();
	/* Configure and enable RTC */
	configure_rtc_count();
	/* Configure and enable callback */
	configure_rtc_callbacks();
	/* Set period */
	rtc_count_set_period( &rtc_instance, 5000);
	TERM_TEXT_WHITE;
	if ( 1 /*ConsoleOn*/) Term_Banner();	
		if ( 1 /*ConsoleOn*/)	printf("\n\rTest CM3-TEST - Ver 0.03\n\r");
	if ( 0 /*ConsoleOn*/) printf("YARM CM3 11 2017 common Libs %s %s\r\n",__DATE__, __TIME__);	
	TERM_TEXT_DEFAULT;
	
	printf("Sensor Data Packet Length = %d\r\n", SENSOR_DATA_LEN);

	
// Test ADC
#if 0	
	for (;;) {
		printf("\n\rTest ADC CM3-TEST - Ver 0.03\n\r");
		menuADC_Yarm();
		c=getchar();


		// Read ADC
		// ADC_POSITIVE_INPUT_PIN19
		// ADC_POSITIVE_INPUT_PIN18
		// ADC_POSITIVE_INPUT_PIN0
		// ADC_POSITIVE_INPUT_PIN1
			
		if (c=='r') {
			printf("Analog 1=%.2f\r\n",read_adc(ADC_POSITIVE_INPUT_PIN0));
			printf("Analog 2=%.2f\r\n",read_adc(ADC_POSITIVE_INPUT_PIN1));
		}
	}
#endif
	
// Test I2C
#if 0
	BME280_Init();
	delay_ms(10);

	printf("\n\rTest GROVE I2C Yarm CM3-TEST - Ver 0.03\n\r");
	menuI2C_Yarm();
	c=getchar();
	for (;;) {
		delay_ms(10);

		// Read I2C BME280
		
//		if (c=='r') {
			BME280_Get_AllValues( &p, &t, &h);
			delay_ms(10);
			if ( ConsoleOn) {
				TERM_TEXT_GREEN;
				printf("Temp:%.2f, Press: %.2f, Hum: %.2f\r\n", t, (p/100), h);
				TERM_TEXT_DEFAULT;
			}
			delay_ms(1000);
		}
//	}


#endif	
	
	
	
	for ( i=0; i<SENSOR_DATA_LEN; i++)
		sd.data[i]=0;
	/* */
	for ( i=0; i<BUF_LENGTH; i++) {
		rd_buffer[i]=0;
	}
	/* MCU ID */
	SerialNumber[0]=*ser_ptr1;
	SerialNumber[1]=*ser_ptr2++;
	SerialNumber[2]=*ser_ptr2++;
	SerialNumber[3]=*ser_ptr2;
	
	if ( ConsoleOn) printf("SerialNumber: 0X %0x %0x %0x %0x\r\n", SerialNumber[0], SerialNumber[1], SerialNumber[2], SerialNumber[3])	;

#if !ROBERTO_WAY
	/* Configurazione I2C per barometro */
	BME280_Init();
	BME280_Get_AllValues( &p, &t, &h);
#endif
	/* Configure SPI and PowerUp ATA8510 */
	YARM_Init();
	delay_ms(1);

	// Set YARM in polling mode 
	YARM_SetPollingMode();
	if ( ConsoleOn) YARM_PrintSysError("YARM_SetPollingMode");

	/* main loop */
	while( 1)	{
#if 0
		/* Sleep 
		 * standby (d) = 4uA
		 * idle    (c) = 200uA
		 * dynamic (q) = 7uA
		*/
#if 1
		EnterSleepMode2();	// OK	
#else
		EnterIdleMode();
#endif
#endif	
		/* Evento dalla radio */
		if ( event_radio) {
			event_radio=0;
			RX_FromYarmHarvest1();
			
			delay_ms(1);
			TX_ToYarmHarvest1();
		}
	}
}

