/***************************************************************************** 
* 
* File Name : main.c
* 
* Description: main 
* 
* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. 
* All rights reserved. 
* 
* Author : dave
* 
* Date : 2014-6-14
*****************************************************************************/ 
#include <string.h>
#include "nano_shell_server_task.h"
#include "wm_include.h"
#include "wm_gpio_afsel.h"
#include "nano_shell.h"
#include "nano_shell_interface.h"
#include "lwip/netif.h"
#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#include "app_common.h"
#include "NRF24L01P.h"
#include "app_utils.h"

tls_os_task_t nano_shell_task_handle = NULL;
tls_os_task_t nano_shell_server_task_handle = NULL;
extern s16 uart0_rx_callback(u16 len, void *user_data);
extern s16 uart1_rx_callback(u16 len, void *user_data);

#define NANO_SHELL_TASK_STK_SIZE 640
#define NANO_SHELL_SERVER_TASK_STK_SIZE 640
#define PWM_STATUS_LED WM_IO_PB_25
#define FADE_DOWN 1
#define FADE_UP -1
#define FADE_LOW_THRESHOLD 255
#define FADE_HIGH_THRESHOLD 200
#define PULSE_FAST 3
#define PULSE_SLOW 12


u8 pulse_rate = PULSE_SLOW;
bool nrf_irq = false;

void tls_netif_status_event_cb(u8 status)
{
	struct netif *netif = tls_get_netif();
	switch(status)
  	{
		case NETIF_WIFI_JOIN_SUCCESS:
			shell_printf("Evt : NETIF_WIFI_JOIN_SUCCESS"NEW_LINE);
	  		break;
		case NETIF_WIFI_JOIN_FAILED:
			shell_printf("Evt : NETIF_WIFI_JOIN_FAILED"NEW_LINE);
	  		break;
		case NETIF_WIFI_DISCONNECTED:
			shell_printf("Evt : NETIF_WIFI_DISCONNECTED"NEW_LINE);
			pulse_rate = PULSE_SLOW;
			break;
		case NETIF_IP_NET_UP:
			shell_printf("Evt : NETIF_IP_NET_UP"NEW_LINE"ip addr : %v"NEW_LINE"netmask : %v"NEW_LINE"gateway : %v"NEW_LINE, netif->ip_addr.addr,
			netif->netmask.addr,
			netif->gw.addr);
			pulse_rate = PULSE_FAST;
			break;
		case NETIF_WIFI_SOFTAP_SUCCESS:
			shell_printf("Evt : NETIF_WIFI_SOFTAP_SUCCESS"NEW_LINE);
			break;
		case NETIF_WIFI_SOFTAP_FAILED:
			shell_printf("Evt : NETIF_WIFI_SOFTAP_FAILED"NEW_LINE);
			break;
		case NETIF_WIFI_SOFTAP_CLOSED:
			shell_printf("Evt : NETIF_WIFI_SOFTAP_CLOSED"NEW_LINE);
			pulse_rate = PULSE_SLOW;
			break;
		case NETIF_IP_NET2_UP:
			shell_printf("Evt : NETIF_IP_NET2_UP"NEW_LINE"ip addr : %v"NEW_LINE"netmask : %v"NEW_LINE"gateway : %v"NEW_LINE, netif->next->ip_addr.addr,
			netif->next->netmask.addr,
			netif->next->gw.addr);
			pulse_rate = PULSE_FAST;
			break;
		case NETIF_IPV6_NET_UP:
			shell_printf("Evt : NETIF_IPV6_NET_UP"NEW_LINE);
			break;
		default:
			shell_printf("Evt : UNKNOWN"NEW_LINE);
			break;
  }
}

void touchsensor_cb(u32 status)
{
	shell_printf("Touch detected : status(%u)"NEW_LINE, status);
}

void tls_gpio_irq_cb(void *arg)
{
	tls_clr_gpio_irq_status(WM_IO_PB_07);
}

void tls_gpio_pb11_irq_cb(void *arg)
{
	tls_clr_gpio_irq_status(WM_IO_PB_11);
	nrf_irq = true;
}

void delay_ms(uint32_t ms)
{
    tls_os_time_delay(pdMS_TO_TICKS(ms));
}

uint32_t elapsed_ms(void)
{
    return millis();
}

void CE_HIGH(void)
{
    tls_gpio_write(WM_IO_PB_10, 1);
}

void CE_LOW(void)
{
    tls_gpio_write(WM_IO_PB_10, 0);
}

void user_main(void *param)
{
	u8 pwm_led_duty_cycle = 255;
	s8 fading_direction = FADE_UP;

	//We initialize input/output used by the app
	wm_pwm3_config(PWM_STATUS_LED);
	tls_pwm_init(3, 1000, 0, 0);
	wm_uart1_tx_config(WM_IO_PB_06);
	wm_uart1_rx_config(WM_IO_PB_07);
	tls_gpio_irq_enable(WM_IO_PB_07, WM_GPIO_IRQ_TRIG_DOUBLE_EDGE);
	tls_gpio_isr_register(WM_IO_PB_07, &(tls_gpio_irq_cb), NULL);
	
	//We set a a pin as touch sensor :
	wm_touch_sensor_config(WM_IO_PA_07);
	tls_touchsensor_threshold_config(1, 120);
	tls_touchsensor_init_config(1, 16, 16,1);
	tls_touchsensor_irq_enable(1);
	tls_touchsensor_irq_register(&(touchsensor_cb));

	//We set the CE and IRQ pin for the NRF module
	tls_gpio_cfg(WM_IO_PB_10, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING); //CE pin
	tls_gpio_cfg(WM_IO_PB_11, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);  //IRQ pins
	tls_gpio_irq_enable(WM_IO_PB_11, WM_GPIO_IRQ_TRIG_FALLING_EDGE);
	tls_gpio_isr_register(WM_IO_PB_11, &(tls_gpio_pb11_irq_cb), NULL);


	//We init the uart 1
	tls_uart_port_init(TLS_UART_1, NULL, 0);

	//We create and start a timer to run the millis counter
	struct tls_timer_cfg tmr_millis = {0};
	tmr_millis.arg = NULL;
	tmr_millis.is_repeat = true;
	tmr_millis.timeout = 1;
	tmr_millis.unit = TLS_TIMER_UNIT_MS;
	tmr_millis.callback = &(millis_run_cb);
	u8 tmr_millis_id = tls_timer_create(&tmr_millis);
	tls_timer_start(tmr_millis_id);

	//We create a task for the nano_shell process
	u8 *nano_shell_task_stack = NULL, *nano_shell_server_task_stack = NULL;

	tls_uart_rx_callback_register(TLS_UART_0, &(uart0_rx_callback), NULL);
	tls_uart_rx_callback_register(TLS_UART_1, &(uart1_rx_callback), NULL);

	//we test the NRF lib here
	NRF24L01P_t NRF;
	shell_printf("Checking NRF setup."NEW_LINE);
	shell_printf("Setting SPI to 1 Mhz : %d."NEW_LINE, tls_spi_setup(SPI_DEFAULT_MODE, SPI_CS_ACTIVE_MODE, 8000000));
	shell_printf("NRF begin : %d."NEW_LINE, NRF24L01P_begin(&NRF));
	shell_printf("Is NRF connected : %d."NEW_LINE, NRF24L01P_isChipConnected(&NRF));
	//NRF24L01P_setChannel(&NRF, 2);
	NRF24L01P_setPALevel(&NRF, RF24_PA_LOW, false);
	//NRF24L01P_setDataRate(&NRF, RF24_250KBPS);
	//NRF24L01P_setRetries(&NRF, 8, 15);
	NRF24L01P_enableDynamicPayloads(&NRF);
	NRF24L01P_enableAckPayload(&NRF);
	NRF24L01P_maskIRQ(&NRF, true, true, false);
	
	const uint8_t ADDR[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7};
	const uint8_t ack_pl[] = "1234567";
	NRF24L01P_openWritingPipe(&NRF, "1Node");
	NRF24L01P_openReadingPipe(&NRF, 1, "2Node");
	NRF24L01P_writeAckPayload(&NRF, 1, ack_pl, sizeof ack_pl);
	NRF24L01P_startListening(&NRF);
	shell_printf("NRF PA level : %d"NEW_LINE, NRF24L01P_getPALevel(&NRF));
	NRF24L01P_printDetails(&NRF);
	/*uint8_t payload[32] = "Hello W801";
	shell_printf("Sending payload : %d"NEW_LINE, NRF24L01P_write(&NRF, payload, sizeof payload));
	NRF24L01P_printDetails(&NRF);*/

	nano_shell_server_task_stack = tls_mem_alloc(sizeof(u32) * NANO_SHELL_SERVER_TASK_STK_SIZE);
	if(nano_shell_server_task_stack != NULL)
	{
		tls_os_status_t status = tls_os_task_create(
													&nano_shell_server_task_handle,
													"shll_srv",
													&(nano_shell_server_task),
													NULL,
													(void*) nano_shell_server_task_stack,
													NANO_SHELL_SERVER_TASK_STK_SIZE * sizeof(u32_t),
													62,
													0
												);
		if(status != TLS_OS_SUCCESS)
			shell_printf("Failed to create nano shell server task."NEW_LINE);
	}
	
	nano_shell_task_stack = tls_mem_alloc(sizeof(u32) * NANO_SHELL_TASK_STK_SIZE);
	if(nano_shell_task_stack != NULL)
	{
		tls_os_task_create(
			&nano_shell_task_handle,
			"na_shell",
			&(nano_shell_loop),
			NULL,
			(void*) nano_shell_task_stack,
			NANO_SHELL_TASK_STK_SIZE * sizeof(u32),
			62,
			0
		);
	}

	shell_printf("Registering netif callback."NEW_LINE);
	tls_netif_add_status_event(&(tls_netif_status_event_cb));

	for(;;)
	{
		tls_pwm_duty_set(3, pwm_led_duty_cycle);
		if(pwm_led_duty_cycle == FADE_LOW_THRESHOLD)
		{
			fading_direction = FADE_UP;
			tls_os_time_delay(pdMS_TO_TICKS(pulse_rate == PULSE_SLOW ? 500 : 100));
		}	
		else if(pwm_led_duty_cycle == FADE_HIGH_THRESHOLD)
		{
			fading_direction = FADE_DOWN;
			tls_os_time_delay(pdMS_TO_TICKS(pulse_rate == PULSE_SLOW ? 500 : 100));
		}
			
		pwm_led_duty_cycle+=fading_direction;

		tls_os_time_delay(pdMS_TO_TICKS(pulse_rate));

		if(nrf_irq)
		{
			bool tx_ok, tx_fail, rx_ready;
			NRF24L01P_whatHappened(&NRF, &tx_ok, &tx_fail, &rx_ready);
			shell_printf("NRF event : tx_ok %d, tx_fail %d and rx_ready : %d, rx fifo full ? %u, tx fifo full ? %u"NEW_LINE, tx_ok, tx_fail, rx_ready, NRF24L01P_rxFifoFull(&NRF), NRF24L01P_txFifoFull(&NRF));

			if(NRF24L01P_available(&NRF))
			{
				char payload[32] = "";
				NRF24L01P_read(&NRF, payload, 8);
				shell_printf("Received : #%s#\r\n", payload);
				NRF24L01P_writeAckPayload(&NRF, 1, ack_pl, sizeof ack_pl);
			}

			nrf_irq = false;
		}
	}
}

