/**
 ******************************************************************************
 *
 * @file        Sample_EMB_Init.c
 *
 * @brief       This is the C code format driver file.
 *
 * @par         Project
 *              MG32
 * @version     V2.11
 * @date        2021/05/25
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2019 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. 
 ******************************************************************************
 ******************************************************************************
 */


/* Includes ------------------------------------------------------------------*/
#include "Sample_EMB_Init.h"
#include "Sample__Common.h"


/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static Sample_EMB_HandleTypeDef gSEMB;

/* Private function prototypes -----------------------------------------------*/
void Sample_EMB_Access(void);

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External vairables --------------------------------------------------------*/





/**
 *******************************************************************************
 * @brief       Config the EMB peripheral for External Device.
 * @details     1. EMB Initialze
 *      \n      2. Check Target device Ready
 *      \n      3. Write Data to Target device.
 *      \n      4. Read Data from Target device.
 *
 * @return      No
 * @exception   None
 * @note        
 * @par         Example
 * @code        
 * @endcode     
 * @par         Modify
 *              void Sample_EMB_Access(void)
 *******************************************************************************
 */
static volatile uint32_t gTemp32 __attribute__((section(".ARM.__at_0x60000020")));
static volatile uint16_t gTemp16 __attribute__((section(".ARM.__at_0x60000030")));
static volatile uint8_t gTemp8 __attribute__((section(".ARM.__at_0x60000040")));


void Sample_EMB_Access(void)
{
    gSEMB.Instance = EMB;
    // SMP_Return Sample_EMB_Init(Sample_EMB_HandleTypeDef *SI2C);
    Sample_EMB_Init(&gSEMB);

  // Word Access
    // Write 32Bit Data
    *(uint32_t *)0x60000000 = 0x12345678;
    *(uint32_t *)0x60000004 = 0x0FEDCBA9;

    // Read 32Bit Data
    gTemp32 = *(uint32_t *)0x60000000;
    gTemp32 = *(uint32_t *)0x60000004;

  // Half Word Access
    // Write 16Bit Data
    *(uint16_t *)0x60000008 = 0x0FED;
    *(uint16_t *)0x6000000A = 0xCBA9;
    *(uint16_t *)0x6000000C = 0x1234;
    *(uint16_t *)0x6000000E = 0x5678;

    // Read 16Bit Data
    gTemp16 = *(uint16_t *)0x60000008;
    gTemp16 = *(uint16_t *)0x6000000A;
    gTemp16 = *(uint16_t *)0x6000000C;
    gTemp16 = *(uint16_t *)0x6000000E;

  // Byte Access
    // Write 32Bit Data
    *(uint8_t *)0x60000010 = 0xF0;
    *(uint8_t *)0x60000011 = 0xE1;
    *(uint8_t *)0x60000012 = 0xD2;
    *(uint8_t *)0x60000013 = 0xC3;
    *(uint8_t *)0x60000014 = 0xB4;
    *(uint8_t *)0x60000015 = 0xA5;
    *(uint8_t *)0x60000016 = 0x96;
    *(uint8_t *)0x60000017 = 0x87;

    // Read 32Bit Data
    gTemp8 = *(uint8_t *)0x60000010;
    gTemp8 = *(uint8_t *)0x60000011;
    gTemp8 = *(uint8_t *)0x60000012;
    gTemp8 = *(uint8_t *)0x60000013;
    gTemp8 = *(uint8_t *)0x60000014;
    gTemp8 = *(uint8_t *)0x60000015;
    gTemp8 = *(uint8_t *)0x60000016;
    gTemp8 = *(uint8_t *)0x60000017;
}



/**
 *******************************************************************************
 * @brief       DeInitialize I2C peripheral
 * @details     Enable CSC to SPI clock
 *
 * @param[in]   sEMB : Sample_I2C pointer to a Sample_I2C_HandleTypeDef 
 *              structure that contains the configuration information for the
 *              specified I2C.
 * @return      DRV_Return
 * @note        
 * @par         Example
 * @code
                Sample_I2C_DeInit(&I2C0_Init);
                Sample_I2C_DeInit(&I2C1_Init);
 * @endcode
 *******************************************************************************
 */
SMP_Return Sample_EMB_DeInit(Sample_EMB_HandleTypeDef *sEMB)
{
    if(__I2C_GetFlagStatus(sEMB->Instance, I2C_FLAG_BUSYF))
        return SMP_Busy;

    __I2C_Disable(sEMB->Instance);

    sEMB->Instance->CR0.W = (uint32_t)0x00000104;
    sEMB->Instance->STA.W = EMB_STA_WPEF_mask_w;
    sEMB->Instance->INT.W = 0;
    sEMB->Instance->CLK.W = 0;
    sEMB->Instance->CR1.W = 0;
    sEMB->Instance->CR2.W = 0;

    return SMP_Success;
}



/**
 *******************************************************************************
 * @brief       Initialize the EMB peripheral.
 * @details     1. GPIO Initial
 *      \n      1.1 CSC Config for GPIO
 *      \n      1.2 GPIO Pin Config
 *      \n      2   CSC Config for EMB
 *      \n      3   NVIC Config for EMB
 *      \n      4.  EMB Initial
 *      \n      4.1 EMB CR0 Bus Type Config.
 *      \n      4.2 EMB CR1 Bus Type Config.
 *      \n      4.3 EMB CR2 Access Timming Config
 *      \n      4.4 EMB STA / INT Interrupt Config
 *      \n      4.5 EMB Enable
 *
 * @param[in]   sEMB : Sample_EMB pointer to a Sample_EMB_HandleTypeDef 
 *              structure that contains the configuration information for the
 *              specified EMB.
 * @return      SMP_Return
 * @exception   None
 * @note        
 * @par         Example
 * @code        
                Sample_EMB_Init(gSEMB)
 * @endcode     
 * @par         Modify
 *              SMP_Return Sample_EMB_Init(Sample_EMB_HandleTypeDef *sEMB)
 *******************************************************************************
 */
SMP_Return Sample_EMB_Init(Sample_EMB_HandleTypeDef *sEMB)
{
//    PIN_InitTypeDef PINX_AddrDataBus;    // With Address and Data Bus, Add Control

    //===== Check EMB Busy =====//
    if((sEMB->Instance->STA.W & EMB_STA_BUSYF_mask_w) != 0)
        return SMP_Busy;

    // Disable EMB
    sEMB->Instance->CR0.W &= ~EMB_CR0_EN_mask_w;

//  //===== GPIO Initial =====//
//    //===== CSC for GPIO Config =====//
//    UnProtectModuleReg(CSCprotect);                                             // Unprotect CSC module
//    CSC_PeriphOnModeClock_Config(CSC_ON_PortA, ENABLE);                         // Enable PortA clock
//    CSC_PeriphOnModeClock_Config(CSC_ON_PortB, ENABLE);                         // Enable PortB clock
//    CSC_PeriphOnModeClock_Config(CSC_ON_PortC, ENABLE);                         // Enable PortC clock
//    CSC_PeriphOnModeClock_Config(CSC_ON_PortD, ENABLE);                         // Enable PortD clock
//    CSC_PeriphOnModeClock_Config(CSC_ON_PortE, ENABLE);                         // Enable PortE clock
//    ProtectModuleReg(CSCprotect);                                               // protect CSC module

//    //===== GPIO Config =====//
//    PINX_AddrDataBus.PINX_Mode               = PINX_Mode_PushPull_O;            // Pin select Digital Input mode
//    PINX_AddrDataBus.PINX_PUResistant        = PINX_PUResistant_Disable;        // Enable pull up resistor
//    PINX_AddrDataBus.PINX_Speed              = PINX_Speed_High;           
//    PINX_AddrDataBus.PINX_OUTDrive           = PINX_OUTDrive_Level0;            // Pin output driver full strength.
//    PINX_AddrDataBus.PINX_FilterDivider      = PINX_FilterDivider_Bypass;       // Pin input deglitch filter clock divider bypass
//    PINX_AddrDataBus.PINX_Inverse            = PINX_Inverse_Disable;            // Pin input data not inverse
//    PINX_AddrDataBus.PINX_Alternate_Function = 8;                               // Pin AFS = 8

//    // Address Bus
//    GPIO_PinMode_Config(PINA(0), &PINX_AddrDataBus);                            // EMB AD0 setup at PA0
//    GPIO_PinMode_Config(PINA(1), &PINX_AddrDataBus);                            // EMB AD1 setup at PA1
//    GPIO_PinMode_Config(PINA(2), &PINX_AddrDataBus);                            // EMB AD2 setup at PA2
//    GPIO_PinMode_Config(PINA(3), &PINX_AddrDataBus);                            // EMB AD3 setup at PA3
//    GPIO_PinMode_Config(PINA(4), &PINX_AddrDataBus);                            // EMB AD4 setup at PA4
//    GPIO_PinMode_Config(PINA(5), &PINX_AddrDataBus);                            // EMB AD5 setup at PA5
//    GPIO_PinMode_Config(PINA(6), &PINX_AddrDataBus);                            // EMB AD6 setup at PA6
//    GPIO_PinMode_Config(PINA(7), &PINX_AddrDataBus);                            // EMB AD7 setup at PA7
//    GPIO_PinMode_Config(PINA(8), &PINX_AddrDataBus);                            // EMB AD8 setup at PA8
//    GPIO_PinMode_Config(PINA(9), &PINX_AddrDataBus);                            // EMB AD9 setup at PA9
//    GPIO_PinMode_Config(PINA(10), &PINX_AddrDataBus);                           // EMB AD10 setup at PA10
//    GPIO_PinMode_Config(PINA(11), &PINX_AddrDataBus);                           // EMB AD11 setup at PA11
//    GPIO_PinMode_Config(PINA(12), &PINX_AddrDataBus);                           // EMB AD12 setup at PA12
//    GPIO_PinMode_Config(PINA(13), &PINX_AddrDataBus);                           // EMB AD13 setup at PA13
//    GPIO_PinMode_Config(PINA(14), &PINX_AddrDataBus);                           // EMB AD14 setup at PA14
//    GPIO_PinMode_Config(PINA(15), &PINX_AddrDataBus);                           // EMB AD15 setup at PA15

//    // Data and Address Bus
//    GPIO_PinMode_Config(PINB(8), &PINX_AddrDataBus);                            // EMB MAD0 setup at PB8
//    GPIO_PinMode_Config(PINB(9), &PINX_AddrDataBus);                            // EMB MAD1 setup at PB9
//    GPIO_PinMode_Config(PINB(10), &PINX_AddrDataBus);                           // EMB MAD2 setup at PB10
//    GPIO_PinMode_Config(PINB(11), &PINX_AddrDataBus);                           // EMB MAD3 setup at PB11
//    GPIO_PinMode_Config(PINB(12), &PINX_AddrDataBus);                           // EMB MAD4 setup at PB12
//    GPIO_PinMode_Config(PINB(13), &PINX_AddrDataBus);                           // EMB MAD5 setup at PB13
//    GPIO_PinMode_Config(PINB(14), &PINX_AddrDataBus);                           // EMB MAD6 setup at PB14
//    GPIO_PinMode_Config(PINB(15), &PINX_AddrDataBus);                           // EMB MAD7 setup at PB15
//    GPIO_PinMode_Config(PINB(1), &PINX_AddrDataBus);                            // EMB MAD8 setup at PC1
//    GPIO_PinMode_Config(PINB(2), &PINX_AddrDataBus);                            // EMB MAD9 setup at PC2
//    GPIO_PinMode_Config(PINB(3), &PINX_AddrDataBus);                            // EMB MAD10 setup at PC3
//    GPIO_PinMode_Config(PINB(8), &PINX_AddrDataBus);                            // EMB MAD11 setup at PC8
//    GPIO_PinMode_Config(PINB(9), &PINX_AddrDataBus);                            // EMB MAD12 setup at PC9
//    GPIO_PinMode_Config(PINB(10), &PINX_AddrDataBus);                           // EMB MAD13 setup at PC10
//    GPIO_PinMode_Config(PINB(11), &PINX_AddrDataBus);                           // EMB MAD14 setup at PC11
//    GPIO_PinMode_Config(PINB(12), &PINX_AddrDataBus);                           // EMB MAD15 setup at PC12

//    // Control
//    GPIO_PinMode_Config(PINC(0),&PINX_AddrDataBus);                             // EMB MCLK setup at PC0
//    GPIO_PinMode_Config(PINB(4),&PINX_AddrDataBus);                             // EMB MALE setup at PB4
//    GPIO_PinMode_Config(PIND(12),&PINX_AddrDataBus);                            // EMB MALE2 setup at PD12
//    GPIO_PinMode_Config(PINE(13),&PINX_AddrDataBus);                            // EMB MBW1 setup at PE13
//    GPIO_PinMode_Config(PINC(7),&PINX_AddrDataBus);                             // EMB MBW0 setup at PC7
//    GPIO_PinMode_Config(PINB(7),&PINX_AddrDataBus);                             // EMB MCE setup at PB7
//    GPIO_PinMode_Config(PINB(6),&PINX_AddrDataBus);                             // EMB MWE setup at PB6
//    GPIO_PinMode_Config(PINB(5),&PINX_AddrDataBus);                             // EMB MOE setup at PB5

//  //===== CSC Initial =====//
//    //=== CSC for EMB Config ===//
//    UnProtectModuleReg(CSCprotect);                                             // Unprotect CSC module
//    CSC_PeriphOnModeClock_Config(CSC_ON_EMB, ENABLE);                           // Enable EMB module clock
//    ProtectModuleReg(CSCprotect);                                               // protect CSC module

//  //===== NVIC SYS_IRQn Initial =====//
//    NVIC_EnableIRQ(SYS_IRQn);
//    NVIC_SetPriority(SYS_IRQn, 0);                                              // Suggest SYSTICK Priority = 0

  //=== EMB Config ===//
    // EMB Config
    sEMB->Instance->CR0.W &= (~EMB_CR0_EN_mask_w);

    sEMB->Instance->CLK.W = (0 << EMB_CLK_CK_PSC_shift_w);

    sEMB->Instance->CR0.W = EMB_CR0_WEN_mask_w |
                            //EMB_CR0_SYNC_EN_mask_w |
                            //EMB_CR0_BUS_MDS_multiplex_w |
                            EMB_CR0_BUS_MDS_separated_w |
                            //EMB_CR0_ADR_TWO_mask_w |
                            //EMB_CR0_ADR_SEL_16bit_w |
                            //EMB_CR0_ADR_SEL_24bit_w |
                            //EMB_CR0_ADR_SEL_30bit_w |
                            //EMB_CR0_ALE2_MDS_ale_w |
                            //EMB_CR0_ALE2_MDS_ale2_w |
                            //EMB_CR0_OE_CTL_mask_w |
                            //EMB_CR0_WE_CTL_mask_w |
                            //EMB_CR0_DMA_EN_mask_w |
                            ((uint32_t)0x00000104);

    sEMB->Instance->CR1.W = //EMB_CR1_CE_INV_mask_w |
                            //EMB_CR1_ALE_INV_mask_w |
                            //EMB_CR1_ALE2_INV_mask_w |
                            //EMB_CR1_CLK_INV_mask_w |
                            //EMB_CR1_MA_SWAP_mask_w |
                            //EMB_CR1_MAD_SWAP_mask_w |
                            //EMB_CR1_MAD_BSWAP_mask_w |
                            //EMB_CR1_MAM1_SEL_no_w |
                            //EMB_CR1_MAM1_SEL_mad15_w |
                            //EMB_CR1_MAM1_SEL_bw1_w |
                            //EMB_CR1_MAM1_SEL_ale2_w |
                            //EMB_CR1_CE_SWEN_mask_w |
                            //EMB_CR1_CE_SWO_mask_w |
                            //EMB_CR1_ALE_SWEN_mask_w |
                            //EMB_CR1_ALE_SWO_mask_w |
                            //EMB_CR1_ALE2_SWEN_mask_w |
                            //EMB_CR1_ALE2_SWO_mask_w |
                            //EMB_CR1_BW0_SWEN_mask_w |
                            //EMB_CR1_BW0_SWO_mask_w |
                            //EMB_CR1_BW1_SWEN_mask_w |
                            //EMB_CR1_BW1_SWO_mask_w |
                            //EMB_CR1_OE_MUX_oe_w |
                            //EMB_CR1_OE_MUX_tm10_w |
                            //EMB_CR1_OE_MUX_tm16_w |
                            //EMB_CR1_OE_MUX_tm20_w |
                            //EMB_CR1_WE_MUX_we_w |
                            //EMB_CR1_WE_MUX_tm10_w |
                            //EMB_CR1_WE_MUX_tm16_w |
                            //EMB_CR1_WE_MUX_tm20_w |
                            0;

    sEMB->Instance->CR2.W = // EMB_CR2_ALES_mask_w |
                            // (3 << 4) |                         // EMB_CR2 ALEW
                            // EMB_CR2_ALEH_mask_w |
                            EMB_CR2_ACCS_mask_w |
                            (1 << 16) |                           // EMB_CR2_ACCW
                            // EMB_CR2_ACCH_mask_w |
                            // (1 << 24) |                        // EMB_CR2_IDLE
                            0;

    //===== EMB Interrupt Config =====//
    sEMB->Instance->STA.W = EMB_STA_WPEF_mask_w;
    sEMB->Instance->INT.W = EMB_INT_IEA_mask_w | EMB_STA_WPEF_mask_w;

    //===== I2C Enable =====//
    sEMB->Instance->CR0.W |= EMB_CR0_EN_mask_w;
    return SMP_Success;
}


