/*******************************************************************************
  Main Source File

  Company:
    Microchip Technology Inc.

  File Name:
    main.c

  Summary:
    This file contains the "main" function for a project.

  Description:
    This file contains the "main" function for a project.  The
    "main" function calls the "SYS_Initialize" function to initialize the state
    machines of all modules in the system
 *******************************************************************************/

// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include <stddef.h>                     // Defines NULL
#include <stdbool.h>                    // Defines true
#include <stdlib.h>                     // Defines EXIT_FAILURE
#include "definitions.h"                // SYS function prototypes
#include <stdio.h>
#include <string.h>
#include <stdarg.h>

uint32_t i = 0;
uint8_t USARTRTxBuffer[100];
uint8_t USART5_ReceiveData[1];
volatile uint8_t USART5_IsReceived = 0;
volatile uint8_t USART5_IsTransmitted = 1;
#define SYS_CONSOLE_PRINT_BUFFER_SIZE	200
static char consolePrintBuffer[SYS_CONSOLE_PRINT_BUFFER_SIZE];
volatile uint8_t TC3_HasExpired = 0;
volatile uint8_t TC4_HasExpired = 0;
uint16_t ADC_Result[2];
volatile uint8_t ADC_IsCompleted = 0;
volatile int8_t ADC_ChannelIdx = 0;
// TODO 16.01


void ADC_Complete( ADC_STATUS status, uintptr_t context )
{
    if( status & ADC_INTFLAG_RESRDY_Msk )
    {
        ADC_Result[ADC_ChannelIdx] = ADC_ConversionResultGet();
        ADC_ChannelIdx = ( ADC_ChannelIdx + 1 ) % 2;
        if( ADC_ChannelIdx == 0 )
        {
            ADC_IsCompleted = 1;
        }
    }
}

void USART5_Transmit( uintptr_t context )
{
    USART5_IsTransmitted = 1;
} 

void USART5_Receive( uintptr_t context )
{
    USART5_IsReceived = 1;
}

void TC3_TimerExpired(TC_TIMER_STATUS status, uintptr_t context) 
{
    if( status & TC_INTFLAG_OVF_Msk)
    {
        TC3_HasExpired = 1;
    }
}

void TC4_TimerExpired(TC_TIMER_STATUS status, uintptr_t context) 
{
    if( status & TC_INTFLAG_OVF_Msk)
    {
        TC4_HasExpired = 1;
    }
}

void myprintf(const char *format, ...)
{
    size_t len = 0;
    va_list args = {0};

    va_start(args, format);
    len = vsnprintf(consolePrintBuffer, SYS_CONSOLE_PRINT_BUFFER_SIZE, format, args);
    va_end(args);

    if ((len > 0) && (len < SYS_CONSOLE_PRINT_BUFFER_SIZE))
    {
        consolePrintBuffer[len] = '\0';
        SERCOM5_USART_Write(consolePrintBuffer, len);
        while (SERCOM5_USART_WriteIsBusy());
    }
}

// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );

    TC3_TimerCallbackRegister( TC3_TimerExpired, (uintptr_t )NULL );
    TC3_TimerStart();
    TC4_TimerCallbackRegister( TC4_TimerExpired, (uintptr_t )NULL );
    TC4_TimerStart();

    SERCOM5_USART_ReadCallbackRegister( USART5_Receive, (uintptr_t )NULL );
    SERCOM5_USART_WriteCallbackRegister( USART5_Transmit, (uintptr_t )NULL );
    SERCOM5_USART_Read( USART5_ReceiveData, 1 );

    ADC_CallbackRegister( ADC_Complete, (uintptr_t )NULL );
    ADC_Enable();

    myprintf("\033[2J");   // Clear screen
    myprintf("\033[?25l"); // Hide cursor

    TCC2_PWMStart();

    while ( true )
    {
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );

        if (TC3_HasExpired)
        {
            TC3_HasExpired = 0;
            LED1_Toggle();
            myprintf("\033[1;1H");
            myprintf( "Hello World!" );

            ADC_ConversionStart();
        }

        if (TC4_HasExpired)
        {
            TC4_HasExpired = 0;

            // TODO 16.02


            LED2_Toggle();
        }

        if( USART5_IsReceived )
        {
            USART5_IsReceived = 0;

            myprintf("\033[4;1H");
            myprintf( "Received Data : %1c", USART5_ReceiveData[0] );

            SERCOM5_USART_Read( USART5_ReceiveData, 1 );
        }

        if( ADC_IsCompleted )
        {
            ADC_IsCompleted = 0;

            // TODO 16.03


            myprintf("\033[2;1H");
            myprintf( "VR1 Value : %4d", ADC_Result[0] );
            myprintf("\033[3;1H");
            myprintf( "Temperature Value : %4d", ADC_Result[1] );
        }
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}


/*******************************************************************************
 End of File
*/

