

/**
 ******************************************************************************
 *
 * @file        Sample_main_wizard.C
 * @brief       Audio Output via PWM - demo main c Code.  (Middleware)
 *
 * @par         Project
 *              MG32
 * @version     V1.00
 * @date        2023/05/09
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2017 MegaWin Technology Co., Ltd.
 *              All rights reserved.
 *
 ******************************************************************************* 
 * @par Disclaimer
 * The Demo software is provided "AS IS" without any warranty, either
 * expressed or implied, including, but not limited to, the implied warranties
 * of merchantability and fitness for a particular purpose. The author will
 * not be liable for any special, incidental, consequential or indirect
 * damages due to loss of data or any other reason.
 * These statements agree with the world wide and local dictated laws about
 * authorship and violence against these laws.
 *******************************************************************************
 *******************************************************************************
 */

// ----------------------------------------------------------------------------
// Description:
//  Megawin provides PWM method of timer to output mono audio data.
//
//
// H/W connect:
//  1. TH197B Board. (MG32F02A032 MCU board)
//      1.1 TM36 generate a 187.5KHz PWM signal.
//      1.2 TM10 generate a 8K Hz period interrupt for update TM36 duty cycle.
//  2. DB05-01A Audio Phone In/Out Board.
//      2.1 Audio Out Board is DB05-01A Board.
//      2.2 DB05-01A needs VDD=5V, GND, DAC_OUT0 pin. (DAC_OUT0 connect MG32F02A032's PC0)
//  3. (OPTION) If user has SPI flash then download audio raw data into flash IC.
//      
//      
//      
// PC-AP:
//  If users want to use Megawin MCU flash to save audio original data. Origin audio 
//  raw data cannot be too large. Because the MCU flash size cannot accept audio waw 
//  raw data. Therefore, the user needs to make the audio raw data smaller. For example, 
//  users use the free AP "Wavosaur" to resample raw data to 8KHz, mono and 8-bit formats.
//      
//
//
// Origin Audio raw data (file.wav):            Convert Audio data (Audio1.c) :
// =======================================      =======================================
//  1. 16K Hz sample rate.                       1. 8K Hz sample rate.
//  2. mono channel.                             2. mono channel.
//  3. 16bit data.                               3. 8bit data.
//  4. Total 62.5K bytes ~ 4 second.             4. Total 2400 bytes ~ 3 second.
//
//      
//      
// How to use this file :
//  1. Compiler files.
//  2. Download it to MG32F02A032 MCU.
//  3. Press 'RESET' button to trigger audio output.
// ----------------------------------------------------------------------------


/* Includes ------------------------------------------------------------------*/
#include "MG32_MID.h"
#include "MG32_ChipInit.h"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/

// The Audio raw data size
#define rawData_Size    24000 

/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

// The Audio raw data index
static uint32_t CNT=0;

// The pointer align rawData
static uint8_t *ptr8;

// for PWM output
#ifdef MG32_ConfigerWizard_TM   
    #if CONF_TM36_MODE == 0
        #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)   /* ARM Compiler V6 */
            #pragma clang diagnostic push
            #pragma clang diagnostic ignored "-Wmissing-variable-declarations"
                TM_HandleTypeDef        mTM36;
            #pragma clang diagnostic pop
        #else
            TM_HandleTypeDef        mTM36;                              /* ARM Compiler V5 */         
        #endif
    #else
        extern TM_HandleTypeDef mTM36;              
    #endif 
#else
    #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)       /* ARM Compiler V6 */
        #pragma clang diagnostic push
        #pragma clang diagnostic ignored "-Wmissing-variable-declarations"
            TM_HandleTypeDef        mTM36;
        #pragma clang diagnostic pop
    #else
        TM_HandleTypeDef        mTM36;                                  /* ARM Compiler V5 */
    #endif
#endif

// for 8K Hz period generator
#ifdef MG32_ConfigerWizard_TM   
    #if CONF_TM10_MODE == 0
        #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)   /* ARM Compiler V6 */
            #pragma clang diagnostic push
            #pragma clang diagnostic ignored "-Wmissing-variable-declarations"
                TM_HandleTypeDef        mTM10;
            #pragma clang diagnostic pop
        #else
            TM_HandleTypeDef        mTM10;                              /* ARM Compiler V5 */
        #endif
    #else
        extern TM_HandleTypeDef mTM10;              
    #endif 
#else
    #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)       /* ARM Compiler V6 */
        #pragma clang diagnostic push
        #pragma clang diagnostic ignored "-Wmissing-variable-declarations"
            TM_HandleTypeDef        mTM10;
        #pragma clang diagnostic pop
    #else
        TM_HandleTypeDef        mTM10;                                  /* ARM Compiler V5 */
    #endif
#endif

/* Private function prototypes -----------------------------------------------*/

void Audio_TM36_Init(void);                     // Initial TM36 (PWM output)
void Audio_TM10_Init(void);                     // Initial TM10 (Period generator)
void Audio_GPIO_Init(void);                     // Initial TM36_OC00 (PC0)


/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External vairables --------------------------------------------------------*/
// Audio raw data 
extern uint8_t rawData[];                       // Audio raw data


int main(void)
{        
    
    // ------------------------------------------------------------------------
    // chip initial (User can enable CSC, GPIO, TM, ADC, EXIC ... wizard)
    //  CSC : Initial to AHB=APB=48MHz.
    //  TM36 : Initial TM36 16bit PWM output. PWM output on PC0.
    //  TM10 : Initial TM10 be 8KHz period interrupt.
    //  GPIO : Initial PC0 to TM36_OC00 for PWM output.
    // ------------------------------------------------------------------------
    // Please check configuration wizard file.
    //  1. Config MG32_CSC_Init.h file to operating  working frequency. (48MHz)
    //  2. Config MG32_TM_Init.h file to control TM10 & TM36.
    //      2.1 TM10 needs generate 8K Hz period and change TM36 PWM duty cycle.
    //      2.2 TM36 needs generate 8bit PWM.
    //  3. Config MG32_GPIO_Init.h to set PC0 to TM36_OC00.
    // ------------------------------------------------------------------------
    ChipInit();    
    
    // or user can reference these code without Configuration Wizard file.
#ifndef MG32_ConfigerWizard_GPIO   
    Audio_GPIO_Init();
#endif
#ifndef MG32_ConfigerWizard_TM   
    Audio_TM36_Init();
    Audio_TM10_Init();
#else
    #if CONF_TM36_MODE==0
        Audio_TM36_Init();
    #endif
    #if CONF_TM10_MODE==0
        Audio_TM10_Init();
    #endif
    
#endif

    // ------------------------------------------------------------------------
    // (Interrupt Selection)
    //      1. User can enable "Enable TM10 NVIC" in IRQ_Handler option of Software 
    //         Component of Manage Run-Time Enviroment.
    //      2. or run this "NVIC_EnableIRQ(TM10_IRQn);"
    // ------------------------------------------------------------------------
//    NVIC_EnableIRQ(TM10_IRQn);

    // ------------------------------------------------------------------------
    // Initial data pointer ptr8 aligned rawdata. (Audio raw data, 8K Hz, mono, 8bit)
    // ------------------------------------------------------------------------
    ptr8 = (uint8_t *) &rawData;
    
    while(1)
    {
        //To do......
    }


}

/**
 *******************************************************************************
 * @brief       The Period Elapsed interrupt function.
 *              (Interrupt Event -> TM10_IRQHandler->MID_TM_IRQHandler->MID_TM_PeriodElapsedCallback)
 * @details     Prepare Audio data to TM36_CC0B.
 * @return      No
 *******************************************************************************
 */
void MID_TM_PeriodElapsedCallback(TM_HandleTypeDef* mTM)
{
    uint16_t RightShift4bit_Val;
    
    // ------------------------------------------------------------------------
    // Check output index equal 24000 ?
    // ------------------------------------------------------------------------
    if (CNT == rawData_Size)                    // the size of rawData     
    {
        // Stop Audio output = PWM output zero
        __DRV_TM_SET_COMPARE_B(&mTM36, MID_TM_Channel0, 0x0000);   
        
        __DRV_TM_DISABLE_ITEA(mTM);
        __DRV_TM_CLEAR_FLAG(mTM, 0xFFFFFFFF);   // Clear TM10 all flags
        CNT = 0;
        
        return;                                 // exit TM10 interrupt
    }
    
    // ------------------------------------------------------------------------
    // Output the next audio data
    // ------------------------------------------------------------------------
    RightShift4bit_Val = (uint16_t) ptr8[CNT];
    
    // From TM36_CC0B to TM36_CC0A register
    __DRV_TM_SET_COMPARE_B(&mTM36, MID_TM_Channel0, RightShift4bit_Val);    
    CNT ++;                                     // The next index            
    //
    __DRV_TM_CLEAR_FLAG(mTM, 0xFFFFFFFF);       // Clear TM10 all flags
    
    return;
    
}

/**
 *******************************************************************************
 * @brief       Initial TM36 to be 16 bit PWM output.
 * @details     1. Initial TM36 counter with clock.
 *              2. Config TM36 channel0 to be 16bit PWM output.
 *              3. Set TM36 channel0 duty cycle setting.
 *              4. Start TM36. 
 * @return      No
 *******************************************************************************
 */
void Audio_TM36_Init(void)
{
    TM_OC_InitTypeDef sConfig;
    
    // ------------------------------------------------------------------------
    // 1. Initial TM36 counter with clock.
    mTM36.Instance              = TM36;
    mTM36.Init.TM_CounterMode   = TM_CASCADE_UP;
    mTM36.Init.TM_Period        = 255;
    mTM36.Init.TM_Prescaler     = 0;
    mTM36.State                 = MID_TM_STATE_RESET;

    MID_TM_PWM_Init(&mTM36);
    
    // ------------------------------------------------------------------------
    // 2. Config TM36 channel0 to be 16bit PWM output.
    MID_TM_OC_Struct_Init(&sConfig);            // default initial (output state)
    sConfig.OCMode              = TM_CH_16bit_PWM;
    sConfig.Pulse               = 0;            // Duty cycle = 0%
    MID_TM_PWM_ConfigChannel(&mTM36, &sConfig, MID_TM_Channel0);
    
    // ------------------------------------------------------------------------
    // 3. Updata TM36 channel0 duty cycle (CC0B)
    __DRV_TM_SET_COMPARE_B(&mTM36, MID_TM_Channel0, 0x0000);   
    
    // ------------------------------------------------------------------------
    // 4. Start TM36. 
    MID_TM_PWM_Start(&mTM36, MID_TM_Channel0);  // Channel0 be 16bit PWM output  

}

/**
 *******************************************************************************
 * @brief       Initial TM10 to be 8k Hz period interrupt.
 * @details     1. Initial TM10 counter with clock.
 *              2. Enable TM10 main counter overflow interrupt and ITEA.
 *              3. Start TM36. 
 * @return      No
 *******************************************************************************
 */
void Audio_TM10_Init(void)
{
    // ------------------------------------------------------------------------
    // 1. Initial TM10 counter with clock.
    mTM10.Instance              = TM10;
    mTM10.Init.TM_CounterMode   = TM_CASCADE_UP;
    mTM10.Init.TM_Period        = 5999;
    mTM10.Init.TM_Prescaler     = 0;
    mTM10.State                 = MID_TM_STATE_RESET;

    MID_TM_Base_Init(&mTM10);
    
    // ------------------------------------------------------------------------
    // 2. Enable TM10 main counter overflow interrupt and ITEA.
    __DRV_TM_ENABLE_IT(&mTM10, TM_IT_UPDATE);
    __DRV_TM_ENABLE_ITEA(&mTM10);
    
    // User can enable "Enable TM10 NVIC" in IRQ_Handler option of Software 
    // Component of Manage Run-Time Enviroment.
    //  or run this "NVIC_EnableIRQ(TM10_IRQn);"
    
    // ------------------------------------------------------------------------
    // 3. Start TM36. 
    MID_TM_Base_Start(&mTM10);

}

/**
 *******************************************************************************
 * @brief       Initial TM36_OC00 pin (PC0).
 * @details     Initial TM36_OC00 pin with PPO, AFS=6
 * @return      No
 *******************************************************************************
 */
void Audio_GPIO_Init(void)
{
    GPIO_InitTypeDef    GPIOX;
 
    // Initial TM36_OC00 pin
    GPIOX.Mode          = GPIO_MODE_PUSHPULL_O;
    GPIOX.Pull          = GPIO_PULLUP;
    GPIOX.Speed         = GPIO_SPEED_LOW;
    GPIOX.Inverse       = GPIO_INVERSE_DISABLE;
    GPIOX.OUTDrive      = GPIO_OUTDRIVE_LEVEL0;
    GPIOX.FilterDivider = GPIO_FILTERDIVIDER_BYPASS;
    GPIOX.Alternate     = 6;                            // 6 = TM36_OC00
    
    MID_GPIO_Pin_Init( PINC(0),&GPIOX); 
}




