

/**
 ******************************************************************************
 *
 * @file        Sample_main_wizard.c
 * @brief       Audio Output via PWM - demo main c Code. (Driver)
 *
 * @par         Project
 *              MG32
 * @version     V1.01
 * @date        2021/05/24
 * @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_ChipInit.h"
#include "MG32_DRV.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;

static TM_TimeBaseInitTypeDef TM36Base;         // for PWM output
static TM_TimeBaseInitTypeDef TM10Base;         // for 8K Hz period generator

/* Private function prototypes -----------------------------------------------*/
// TM10 interrupt routine
void TM10_IRQ(void);

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();
#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       TM10 interrupt function.
 * @details     Prepare Audio data to TM36_CC0B.
 * @return      No
 *******************************************************************************
 */
void TM10_IRQ(void)
{
    uint16_t RightShift4bit_Val;
    
    // ------------------------------------------------------------------------
    // Check output index equal 24000 ?
    // ------------------------------------------------------------------------
    if (CNT == rawData_Size)                    // the size of rawData     
    {
        TM_SetCC0B(TM36, 0x0000);               // Stop Audio output = PWM output zero
        TM_ITEA_Cmd(TM10, DISABLE);             // Disable TM10 interrupt
        TM_ClearFlag(TM10, 0xFFFFFFFF);         // Clear TM10 all flags
        CNT = 0;
        
        return;                                 // exit TM10 interrupt
    }
    
    // ------------------------------------------------------------------------
    // Output the next audio data
    // ------------------------------------------------------------------------
    RightShift4bit_Val = (uint16_t) ptr8[CNT];
    TM_SetCC0B(TM36, RightShift4bit_Val);       // From TM36_CC0B to TM36_CC0A register
    CNT ++;                                     // The next index            
    //
    TM_ClearFlag(TM10, 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. Enable TM36_OC00 output pin
 *              5. Start TM36. 
 * @return      No
 *******************************************************************************
 */
void Audio_TM36_Init(void)
{
    // ------------------------------------------------------------------------
    // 1. Initial TM36 counter with clock.
    TM36Base.TM_Prescaler = 0;                    
    TM36Base.TM_CounterMode = Cascade;
    TM36Base.TM_Period = 255;                   // 8 bit PWM -> 256 step 
    TM36Base.TM_MainClockSource = TM_CK_INT;    // internal clock = TM36_PROC
    TM36Base.TM_2ndClockSource = TM_CK_INT;
    TM36Base.TM_MainClockDirection = TM_UpCount;
    TM36Base.TM_2ndClockDirection = TM_UpCount;
    TM36Base.TM_IntClockDivision = TM_IntDIV1;
    
    TM_TimeBase_Init(TM36, &TM36Base);
    
    // ------------------------------------------------------------------------
    // 2. Config TM36 channel0 to be 16bit PWM output.
    TM_CH0Function_Config(TM36, TM_16bitPWM);
    
    // ------------------------------------------------------------------------
    // 3. Set TM36 channel0 duty cycle setting.
    TM_SetCC0A(TM36, 0);
    TM_SetCC0B(TM36, 0);
    
    // ------------------------------------------------------------------------
    // 4. Enable TM36_OC00 output pin
    TM_OC0zOutputState_Init(TM36, CLR);         // TM36 channl0 output default state.
    TM_OC00Output_Cmd(TM36, ENABLE);            // Enable TM36_OC00 pin
    
    // ------------------------------------------------------------------------
    // 5. Start TM36. 
    TM_Timer_Cmd(TM36, ENABLE);

}

/**
 *******************************************************************************
 * @brief       Initial TM10 to be 8k Hz period interrupt.
 * @details     1. Initial TM36 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.
    TM10Base.TM_Prescaler = 0;              
    TM10Base.TM_CounterMode = Cascade;
    TM10Base.TM_Period = 5999;                  // 48M / 8K = 6000    
    TM10Base.TM_MainClockSource = TM_CK_INT;
    TM10Base.TM_2ndClockSource = TM_CK_INT;
    TM10Base.TM_MainClockDirection = TM_UpCount;
    TM10Base.TM_2ndClockDirection = TM_UpCount;
    TM10Base.TM_IntClockDivision = TM_IntDIV1;
    
    TM_TimeBase_Init(TM10, &TM10Base);
    
    // ------------------------------------------------------------------------
    // 2. Enable TM10 main counter overflow interrupt and ITEA.
    TM_IT_Config(TM10, TMx_TIE_IE, ENABLE);
    TM_ITEA_Cmd(TM10, ENABLE);
    
    // 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. 
    TM_Timer_Cmd(TM10, ENABLE);

}

/**
 *******************************************************************************
 * @brief       Initial TM36_OC00 pin (PC0).
 * @details     Initial TM36_OC00 pin with PPO, AFS=6
 * @return      No
 *******************************************************************************
 */
void Audio_GPIO_Init(void)
{
    PIN_InitTypeDef PINX_InitStruct;
 
    // Initial TM36_OC00 pin
    PINX_InitStruct.PINX_Mode				= PINX_Mode_PushPull_O;
    PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Enable;
    PINX_InitStruct.PINX_Speed              = PINX_Speed_Low;
    PINX_InitStruct.PINX_OUTDrive           = PINX_OUTDrive_Level0;
    PINX_InitStruct.PINX_FilterDivider      = PINX_FilterDivider_Bypass;
    PINX_InitStruct.PINX_Inverse            = PINX_Inverse_Disable;
    PINX_InitStruct.PINX_Alternate_Function = 6;
    
    GPIO_PinMode_Config(PINC(0),&PINX_InitStruct);
    
}




