1.3 Adding Application Logic to the Project

  1. To develop and run the Application, use the following steps:

    Open the main.c file of the project and add the following application logic. Add the following code in the main() function:

    uint8_t uartLocalTxBuffer[100] = {0};
    
        /* Initialize all modules */
        DMAC_ChannelCallbackRegister(DMAC_CHANNEL_0, uartDmaChannelHandler_Tx, 0);      
        RTC_Timer32CallbackRegister(rtcEventHandler, 0);
        EIC_CallbackRegister(EIC_PIN_3, SW0_userHandler, 0);
    
        sprintf((char*)uartTxBuffer, "************* Printing Toggling LED rate *************\r\n");
        DMAC_ChannelTransfer(DMAC_CHANNEL_0, uartTxBuffer, \
            (const void *)&(SERCOM4_REGS->USART_INT.SERCOM_DATA), \
            strlen((const char*)uartTxBuffer));
    
        /* Start the timer */
        RTC_Timer32Start();
    
    Figure 1-15. Adding Application Logic to Register Callback Event Handlers
  2. Implement the registered callback event handlers for the peripherals by adding the following code before the main() function.
    static void SW0_userHandler(uintptr_t context)
    {
            changeTempSamplingRate = true;
    }
    
    static void rtcEventHandler (RTC_TIMER32_INT_MASK intCause, uintptr_t context)
    {
        if (intCause & RTC_MODE0_INTENSET_CMP0_Msk)
        {
            isRTCExpired    = true;
        }
    }
    
    static void uartDmaChannelHandler_Tx(DMAC_TRANSFER_EVENT event, uintptr_t contextHandle)
    {
        if (event == DMAC_TRANSFER_EVENT_COMPLETE)
        {
            isUARTTxComplete = true;
        }
    }
    
  3. According to the status of the isRTCExpired and isUARTTxComplete flags (These flags are handled by rtcEventHandler and uartDmaChannelHandler_Tx event handlers when RTC Timer expires and when UART completes the transfer of data.), the LED0 is toggled at a default rate of 500 ms. To change the toggling rate, if the user presses the SW0 switch, the toggling rate changes to 1s, 2s, and 4s and back to 500 ms with subsequent switch press events. SW0_userHandler will be responsible for changing the toggling rate when the user presses the SW0 switch on the board.

    Inside the while loop, delete SYS_Tasks()and add the following code to toggle the LED at a default rate of 500 ms.

    if ((isRTCExpired == true) && (true == isUARTTxComplete))
                {
                    isRTCExpired = false;
                    isUARTTxComplete = false;
                    LED0_Toggle();
                    sprintf((char*)(uartTxBuffer), "Toggling LED at %s rate \r\n", &timeouts[(uint8_t)tempSampleRate][0]);
                    DMAC_ChannelTransfer(DMAC_CHANNEL_0, uartTxBuffer, \
                        (const void *)&(SERCOM4_REGS->USART_INT.SERCOM_DATA), \
                        strlen((const char*)uartTxBuffer));
                }
    
  4. Add the following code immediately after adding the above code to change the toggling rate when there is a switch press event.
    if(changeTempSamplingRate == true)
                {
                    changeTempSamplingRate = false;
                    if(tempSampleRate == TEMP_SAMPLING_RATE_500MS)
                    {
                        tempSampleRate = TEMP_SAMPLING_RATE_1S;
                        RTC_Timer32CompareSet(PERIOD_1S);
                    }
                    else if(tempSampleRate == TEMP_SAMPLING_RATE_1S)
                    {
                        tempSampleRate = TEMP_SAMPLING_RATE_2S;
                        RTC_Timer32CompareSet(PERIOD_2S);
                    }
                    else if(tempSampleRate == TEMP_SAMPLING_RATE_2S)
                    {
                        tempSampleRate = TEMP_SAMPLING_RATE_4S;
                        RTC_Timer32CompareSet(PERIOD_4S);
                    }
                    else if(tempSampleRate == TEMP_SAMPLING_RATE_4S)
                    {
                       tempSampleRate = TEMP_SAMPLING_RATE_500MS;
                       RTC_Timer32CompareSet(PERIOD_500MS);
                    }
                    else
                    {
                        ;
                    }
                    RTC_Timer32CounterSet(0);
                    sprintf((char*)uartLocalTxBuffer, "LED Toggling rate is changed to %s\r\n", &timeouts[(uint8_t)tempSampleRate][0]);
                    DMAC_ChannelTransfer(DMAC_CHANNEL_0, uartLocalTxBuffer, \
                        (const void *)&(SERCOM4_REGS->USART_INT.SERCOM_DATA), \
                        strlen((const char*)uartLocalTxBuffer));
                }
    
  5. Add the following code to include the necessary header files, and define the macros for different RTC compare values.
    #include <stdio.h>
                  // SYS function prototypes
    
    /* Timer Counter Time period match values for input clock of 4096 Hz */
    #define PERIOD_500MS                    512
    #define PERIOD_1S                       1024
    #define PERIOD_2S                       2048
    #define PERIOD_4S                       4096
    
    #define TX_BUFFER_SIZE 100
    

    This code declares the various flags whose status is monitored and changed by the event handlers in the application. It has various declarations and definitions of arrays used to print the LED toggling rate on the console.

    static volatile bool isRTCExpired = false;
    static volatile bool changeTempSamplingRate = false;
    static volatile bool isUARTTxComplete = true;
    static volatile bool isUARTRxComplete = false;
    static uint8_t uartTxBuffer[TX_BUFFER_SIZE] = {0};
    typedef enum
    {
        TEMP_SAMPLING_RATE_500MS = 0,
        TEMP_SAMPLING_RATE_1S = 1,
        TEMP_SAMPLING_RATE_2S = 2,
        TEMP_SAMPLING_RATE_4S = 3,
    } TEMP_SAMPLING_RATE;
    
    static TEMP_SAMPLING_RATE tempSampleRate = TEMP_SAMPLING_RATE_500MS;
    static const char timeouts[4][20] = {"500 milliSeconds", "1 Second",  "2 Seconds",  "4 Seconds"};