/*******************************************************************************
  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 "TTS_Voice.h"

volatile uint8_t  PCM_Voice  = 0;
volatile uint32_t DMA_BlockSize = 0;
volatile uint32_t DMA_BlockNums = 0;
volatile uint32_t DMA_BlockIndx = 0;

void DMAC0_CompleteCallback(DMAC_TRANSFER_EVENT event, uintptr_t contextHandle)
{
    if( event==DMAC_TRANSFER_EVENT_COMPLETE )
    {
        if( DMA_BlockIndx < DMA_BlockNums )
        {
            uint16_t *srcAddr;
            size_t   blockSize;

            DMA_BlockIndx++;
            blockSize = (TTS_Voice[PCM_Voice].length*2)-(DMA_BlockIndx*DMA_BlockSize);
            if( blockSize>DMA_BlockSize ) blockSize = DMA_BlockSize;
            srcAddr = (uint16_t *)(((uint8_t *)TTS_Voice[PCM_Voice].data)+(DMA_BlockIndx*DMA_BlockSize));
            // Continue remain TSS Wave data
            DMAC_ChannelTransfer( DMAC_CHANNEL_0,                           // channel
                                  (const void *) srcAddr,                   // srcAddr
                                  (const void *) &(DAC_REGS->DAC_DATABUF),  // destAddr
                                  blockSize                                 // blockSize (n Bytes)
                                );
        }
        else
        {
            // Event System Channel 0 User Disable (DAC_VOUT0)
            EVSYS_UserDisable(61U);
        }
    }
}

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

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

    // Register DMAC Complete callback to continue next block transfer
    DMAC_ChannelCallbackRegister( DMAC_CHANNEL_0, DMAC0_CompleteCallback, 0 );

    // Start TC timer
    TC0_CompareStart();

    // Given the DMA block size
#if 0
    DMA_BlockSize = (64*1024*2); // DMA support maximum 64K beats per block = 64K x 16bits(beat size) = 128Bytes
#else
    // The plib_damc has a bug to convert blocksize to 16bit before divided,
    // We use maximum 64Kbyte(16bits) as maximum block size for workaround but not modify bug in plib_damc
    DMA_BlockSize = (64*1024)-1;
#endif

    // Calculate number of blocks (maximum block size)
    DMA_BlockIndx = 0;
    DMA_BlockNums = (TTS_Voice[PCM_Voice].length*2)/DMA_BlockSize;
    if( DMA_BlockNums==0 )
    {
        // Block size less than maximum block size
        DMA_BlockSize = (TTS_Voice[PCM_Voice].length*2);
    }

    // Start DMA Transfer
    DMAC_ChannelTransfer( DMAC_CHANNEL_0,                           // channel
                          (const void *) TTS_Voice[PCM_Voice].data, // srcAddr
                          (const void *) &(DAC_REGS->DAC_DATABUF),  // destAddr
                          DMA_BlockSize                             // blockSize (n Bytes)
                        );

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

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

    return ( EXIT_FAILURE );
}


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

