#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "sdk_common.h"
#include "nrf.h"
#include "nrf_esb.h"
#include "nrf_error.h"
#include "nrf_esb_error_codes.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "boards.h"
#include "nrf_delay.h"
#include "app_util.h"
#include "app_timer.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#include "GpioProcess.h"
#include "EsbProcess.h"

unsigned long	PacketSendCnt = 0;
unsigned long	PacketSendOKCnt = 0;
unsigned long	PacketSentNGCnt = 0;
unsigned long	PacketReceiveOKCnt = 0;
unsigned long	PacketReceiveNGCnt = 0;

void PacketSend(void)
{
    int							i;
    uint8_t						Sum = 0;

	//	printf(" ==> Send Packet back\r\n");
#if 1
	EebTxRxSwitch(TX);
#else
	(void) nrf_esb_stop_rx();
	(void) nrf_esb_flush_tx();
	(void) nrf_esb_start_tx();
#endif
	for (i = 1 ; i < NRF_ESB_MAX_PAYLOAD_LENGTH ; i++ )
		Sum = Sum + tx_payload.data[i];
	tx_payload.data[0] = Sum;
    tx_payload.noack = true;
    if (nrf_esb_write_payload(&tx_payload) == NRF_SUCCESS)
    {
        tx_payload.data[2]++;
    #ifdef	EsbTestUartEnsable
		printf(" [%X %X %X %X %X %X %X %X]\r\n", tx_payload.length, tx_payload.pipe, tx_payload.rssi, tx_payload.noack, tx_payload.pid, tx_payload.data[0], tx_payload.data[1], tx_payload.data[2]);
    	printf(" Send. CheckSum =  %X\r\n", Sum);
        printf(" Send OK\r\n");
    #endif	// EsbTestUartEnsable
        // Toggle one of the LEDs.
    }
    else
    {
        //	printf(" *** Sending packet failed");
    } 
}

void Action_Key1(void)
{
	PacketSend();
}

long	RxLedFlashCnt = 0;
void nrf_esb_event_handler(nrf_esb_evt_t const * p_event)
{
    switch (p_event->evt_id)
    {
        case NRF_ESB_EVENT_TX_SUCCESS:
        	PacketSendOKCnt++;
       	#ifdef	EsbTestUartEnsable
        	printf(" Change to RX\r\n");
        #endif	// EsbTestUartEnsable
            EebTxRxSwitch(RX);
            break;
        case NRF_ESB_EVENT_TX_FAILED:
            //	printf(" TX-Err\r\n");
            (void) nrf_esb_flush_tx();
            (void) nrf_esb_start_tx();
            PacketSentNGCnt++;
            tx_payload.data[3]++;
            nrf_delay_ms(2);
            PacketSend();
            break;
        case NRF_ESB_EVENT_RX_RECEIVED:
        #ifdef	EsbTestUartEnsable
            printf("RX RECEIVED EVENT\r\n");
        #endif	// EsbTestUartEnsable
            while (nrf_esb_read_rx_payload(&rx_payload) == NRF_SUCCESS)
            {
                if (rx_payload.length > 0)
                {
	            	uint8_t			Sum = 0;
            		int				i;
            		for ( i = 1 ; i < NRF_ESB_MAX_PAYLOAD_LENGTH ; i++ )
            			Sum = Sum + rx_payload.data[i];
					if ( Sum == rx_payload.data[0] )
					{
						PacketReceiveOKCnt++;
						//	printf(" I [%X]\r\n", Sum);
						if ( ++RxLedFlashCnt == 50 )
						{
							RxLedFlashCnt = 0;
							nrf_gpio_pin_toggle(GpioLed0);
						}
					}
					else
					{
						PacketReceiveNGCnt++;
                    	printf(" *** Packet NG [%x]---\r\n", Sum);
                    }
                    // Switch PTX, modify content, and send again
                    memcpy(tx_payload.data, rx_payload.data, rx_payload.length);
                    tx_payload.data[3]++;
                    nrf_delay_ms(2);
					PacketSend();
		            //	PacketSend(rx_payload.data[1]);
                }
            }
            break;
    }
}


void clocks_start( void )
{
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART = 1;

    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
}

// ---- APP_TIMER code added here ----
APP_TIMER_DEF(m_esb_tx_timer_id);
APP_TIMER_DEF(Timer_1S_timer_id);

static void esb_send_packet_timer_callback(void *p)
{
    static nrf_esb_payload_t tx_payload = NRF_ESB_CREATE_PAYLOAD(0, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00);
    printf("TX packet sent");
    tx_payload.noack = false;
    if (nrf_esb_write_payload(&tx_payload) == NRF_SUCCESS)
    {
        // Toggle one of the LEDs.
        nrf_gpio_pin_write(LED_1, !(tx_payload.data[1]%8>0 && tx_payload.data[1]%8<=4));
        nrf_gpio_pin_write(LED_2, !(tx_payload.data[1]%8>1 && tx_payload.data[1]%8<=5));
        nrf_gpio_pin_write(LED_3, !(tx_payload.data[1]%8>2 && tx_payload.data[1]%8<=6));
        nrf_gpio_pin_write(LED_4, !(tx_payload.data[1]%8>3));
        tx_payload.data[1]++;
    }
    else
    {
        printf("Sending packet failed");
    } 
}

extern	uint8_t		KeyDebunseTick;
void Timer_1S(void *p)
{
	static uint32_t		sPacketSendOKCnt, sPacketSentNGCnt, sPacketReceiveOKCnt, sPacketReceiveNGCnt;
	printf(" TX: %d/%d, RX: %d/%d\r\n", (PacketSendOKCnt - sPacketSendOKCnt), (PacketSentNGCnt - sPacketSentNGCnt), (PacketReceiveOKCnt - sPacketReceiveOKCnt), (PacketReceiveNGCnt - sPacketReceiveNGCnt));
	sPacketSendOKCnt = PacketSendOKCnt;
	sPacketSentNGCnt = PacketSentNGCnt;
	sPacketReceiveOKCnt = PacketReceiveOKCnt;
	sPacketReceiveNGCnt = PacketReceiveNGCnt;
}

static void timers_init(void)
{
    ret_code_t err_code;
    
    // Start the 32.768 kHz low frequency clock. Without this the app_timer module won't work
    NRF_CLOCK->TASKS_LFCLKSTART = 1;
    
    // Initialize timer module.
    err_code = app_timer_init();
    APP_ERROR_CHECK(err_code); 

    // Create timers.
    err_code = app_timer_create(&m_esb_tx_timer_id, APP_TIMER_MODE_REPEATED, esb_send_packet_timer_callback);
    APP_ERROR_CHECK(err_code);    
	err_code = app_timer_create(&Timer_1S_timer_id, APP_TIMER_MODE_REPEATED, Timer_1S); 
	APP_ERROR_CHECK(err_code);
}

static void timers_start(void)
{
    ret_code_t err_code;
#if 0
    app_timer_start(m_esb_tx_timer_id, APP_TIMER_TICKS(2000/*100*/), (void *)0);
    APP_ERROR_CHECK(err_code);
#endif
    err_code = app_timer_start(Timer_1S_timer_id, APP_TIMER_TICKS(5000/*100*/), (void *)0);
    APP_ERROR_CHECK(err_code);
}
// -----------------------------------

int main(void)
{
    uint32_t err_code;

    gpio_init();

    clocks_start();

    UART_Init();
    printf(" ... Start (RX) ...\r\n");
    timers_init();

    err_code = esb_init(RX);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_esb_start_rx();
    APP_ERROR_CHECK(err_code);

	timers_start();

    while (true)
    {
        // Nothing to do now that the app_timer runs everything, except flush the log and go to sleep
        if(NRF_LOG_PROCESS() == false)
        {
            __WFE();
        }
    }
}
