/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2024. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */
/******************************************************************************
 * @version: V3.1.0  AC7840x  Demo
 ******************************************************************************/

/*!
 * @file adc_sample.c
 *
 * @brief This file provides ADC functions.
 */

/* ===============================  Includes  =============================== */
#include "dma_drv.h"
#include "dma_hw.h"
#include "Dma_Config.h"
#include "spi_w25x16.h"
#include "adc_sample.h"
#include "i2c_master_sample.h"

/* ===============================   Define   =============================== */
#define DMA_ADC_DATA_LEN   (ADC_BUFFER_SIZE * 2)

#define DMA_START_ADDR_ADC0     (0x20000000UL)
#define DMA_START_ADDR_ADC1     (DMA_START_ADDR_ADC0 + DMA_ADC_DATA_LEN)

#define DMA_START_ADDR_I2C_RX   (DMA_START_ADDR_ADC1   + DMA_ADC_DATA_LEN)
#define DMA_START_ADDR_I2C_TX   (DMA_START_ADDR_I2C_RX + AT24C02_MAX_SIZE)

#define DMA_START_ADDR_SPI_TX   (DMA_START_ADDR_I2C_TX  + AT24C02_MAX_SIZE)
#define DMA_START_ADDR_SPI_RX   (DMA_START_ADDR_SPI_TX  + W25X16_DATA_BUF_LEN)
/* ===============================   Typedef  =============================== */

/* ===============================  Variables =============================== */
/* 使用 __attribute__((section(".ARM.__at_0x20000000")))指定地址时需要将所有数据放在同一个源文件中进行 */
#if defined(__ICCARM__)                    /* IAR Compiler */
/* adc 数据数组 */
uint16_t g_adc0_array[ADC_BUFFER_SIZE] @DMA_START_ADDR_ADC0 = {0}; /* DMA搬运的RAM地址需要在SRAM_U区域 */
uint16_t g_adc1_array[ADC_BUFFER_SIZE] @DMA_START_ADDR_ADC1 = {0}; /* DMA搬运的RAM地址需要在SRAM_U区域 */

/* i2c 数据数组 */
uint8_t g_i2cRxBuff[AT24C02_MAX_SIZE] @DMA_START_ADDR_I2C_RX = {0}; /* DMA搬运的RAM地址需要在SRAM_U区域 */
uint8_t g_i2cTxBuff[AT24C02_MAX_SIZE] @DMA_START_ADDR_I2C_TX = {0}; /* DMA搬运的RAM地址需要在SRAM_U区域 */

/* SPI 数据数组 */
uint8_t g_SpiWrDataBuf[W25X16_DATA_BUF_LEN] @DMA_START_ADDR_SPI_TX = {0}; /* DMA搬运的RAM地址需要在SRAM_U区域 */
uint8_t g_SpiRdDataBuf[W25X16_DATA_BUF_LEN] @DMA_START_ADDR_SPI_RX = {0}; /* DMA搬运的RAM地址需要在SRAM_U区域 */
#elif defined(__CC_ARM)                    /* Arm Compiler */
/* adc 数据数组 */
uint16_t g_adc0_array[ADC_BUFFER_SIZE] __attribute__((section(".ARM.__at_0x20000000"))) = {0}; /* DMA搬运的RAM地址需要在SRAM_U区域 */
uint16_t g_adc1_array[ADC_BUFFER_SIZE] __attribute__((section(".ARM.__at_0x20000000"))) = {0}; /* DMA搬运的RAM地址需要在SRAM_U区域 */

/* i2c 数据数组 */
uint8_t g_i2cRxBuff[AT24C02_MAX_SIZE] __attribute__((section(".ARM.__at_0x20000000"))) = {0}; 
uint8_t g_i2cTxBuff[AT24C02_MAX_SIZE] __attribute__((section(".ARM.__at_0x20000000"))) = {0};

/* SPI 数据数组 */
uint8_t g_SpiWrDataBuf[W25X16_DATA_BUF_LEN] __attribute__((section(".ARM.__at_0x20000000"))) = {0};  /* DMA搬运的RAM地址需要在SRAM_U区域*/
uint8_t g_SpiRdDataBuf[W25X16_DATA_BUF_LEN] __attribute__((section(".ARM.__at_0x20000000"))) = {0};  /* DMA搬运的RAM地址需要在SRAM_U区域*/
#endif

/*! dma state */
dma_chn_state_t g_dma_adc0_chn_state   = {0x0};
dma_chn_state_t g_dma_adc1_chn_state   = {0x0};
dma_chn_state_t g_dma_i2c_txchn_state  = {0x0};
dma_chn_state_t g_dma_spi_txchn_state  = {0x0};
dma_chn_state_t g_dma_spi_rxchn_state  = {0x0};

dma_state_t g_dma_state = {
    .virtChnState[0] = &g_dma_adc0_chn_state,
    .virtChnState[1] = &g_dma_adc1_chn_state,
    .virtChnState[2] = &g_dma_i2c_txchn_state,
    .virtChnState[3] = &g_dma_spi_txchn_state,
    .virtChnState[4] = &g_dma_spi_rxchn_state,
};

/*! @brief ADC0 DMA channel configure */
dma_channel_config_t s_Adc0DmaChConfig = {
    .channelPriority = DMA_CHN_PRIORITY_HIGH, /*! dma channel priority */
    .virtChnConfig   = DMA_ADC0_CHANNEL,      /*! dma virtual channel number */
    .source          = DMA_REQ_ADC0,          /*! dma channel request adc0 tx */
    .callback        = NULL,                  /*! no callback function */
    .enableTrigger   = false,                 /*! dma periodic trigger disable */
};

/*! @brief ADC1 DMA channel configure */
dma_channel_config_t s_Adc1DmaChConfig = {
    .channelPriority = DMA_CHN_PRIORITY_HIGH, /*! dma channel priority */
    .virtChnConfig   = DMA_ADC1_CHANNEL,      /*! dma virtual channel number */
    .source          = DMA_REQ_ADC1,          /*! dma channel request adc0 tx */
    .callback        = NULL,                  /*! no callback function */
    .enableTrigger   = false,                 /*! dma periodic trigger disable */
};

/*! @brief I2C Tx DMA channel configure */
dma_channel_config_t s_I2cMasterTxDmaChConfig = {
    .channelPriority = DMA_CHN_PRIORITY_HIGH,  /*! dma 通道优先级 */
    .virtChnConfig   = DMA_I2C_CHANNEL,        /*! dma 通道号 */
    .source          = DMA_REQ_I2C0_TX,        /*! i2c0 发送的dma通道请求  */
    .callback        = NULL,                   /*! 无回调函数 */
    .enableTrigger   = false,                  /*! dma 周期触发禁能 */
};

/*! @brief SPI Rx DMA channel configure */
dma_channel_config_t s_SpiMasterRxDmaChConfig =
{
    .channelPriority = DMA_CHN_PRIORITY_MEDIUM, /*! 配置DMA通道优先级 */
    .virtChnConfig = DMA_SPIRX_CHANNEL,         /*! 配置DMA通道号 */
    .source = DMA_REQ_SPI0_RX,                  /*! 配置触发DMA请求源 */
    .callback = NULL,                           /*! 配置回调函数，用户无法注册回调函数，因为库里边回去清空回调函数 */
    .callbackParam = NULL,                      /*! 配置回调函数参数 */
    .enableTrigger = false,                     /*! 去能DMA循环模式*/
};

/*! @brief SPI Tx DMA channel configure */
dma_channel_config_t s_SpiMasterTxDmaChConfig =
{
    .channelPriority = DMA_CHN_PRIORITY_MEDIUM, /*! 设置DMA通道优先级 */
    .virtChnConfig = DMA_SPITX_CHANNEL,         /*! 配置DMA通道号 */
    .source = DMA_REQ_SPI0_TX,                  /*! 配置触发DMA请求源 */
    .callback = NULL,                           /*! 配置回调函数，用户无法注册回调函数，因为库里边回去重新注册覆盖掉用户回调函数 */
    .callbackParam = NULL,                      /*! 配置回调函数参数 */
    .enableTrigger = false,                     /*! 去能DMA循环模式*/
};

/* =========================  Functions declaration  ======================== */

/* =========================  Functions definition  ========================= */

/*!
 * @brief 配置ADC使用DMA传输
 *
 * @param[in]  none
 *
 * @return none
 */
void ADC_DmaConfig(void)
{
    /* ADC0 DMA Config */
    DMA_DRV_ConfigTransfer(DMA_ADC0_CHANNEL, DMA_TRANSFER_PERIPH2MEM, (uint32_t)(ADC0->RDR), (uint32_t)g_adc0_array, DMA_TRANSFER_SIZE_2B, DMA_ADC_DATA_LEN); /*! DMA传输配置 */

    DMA_DRV_SetSrcAddr(DMA_ADC0_CHANNEL, (uint32_t)(&(ADC0->RDR[0])), (uint32_t)(&(ADC0->RDR[ADC0_CHANNEL_NUM]))); /*! 由于需要读取的源地址为ADC0的RDR0~RDR3寄存器，每个寄存器占四个字节，程序需要
                                                                                             读取每个寄存器的低位两个字节，此处需要修改DMA源地址的结束地址 */
    DMA_DRV_SetSrcOffset(DMA_ADC0_CHANNEL, 4);                                                      /*! DMA_TRANSFER_PERIPH2MEM类型的DMA只能传输一个固定的寄存器地址，此处修改偏移量
                                                                                             为4，读取完一个寄存器后地址加4，指向下一个寄存器，实现多个寄存器的连续读取*/
    DMA_DRV_SetCircularMode(DMA_ADC0_CHANNEL, true);                                                /*! 打开DMA循环模式 */
    DMA_DRV_StartChannel(DMA_ADC0_CHANNEL);                                                         /*! 使能DMA通道 */
    
    /* ADC1 DMA Config */
    DMA_DRV_ConfigTransfer(DMA_ADC1_CHANNEL, DMA_TRANSFER_PERIPH2MEM, (uint32_t)(ADC1->RDR), (uint32_t)g_adc1_array, DMA_TRANSFER_SIZE_2B, DMA_ADC_DATA_LEN); /*! DMA传输配置 */

    DMA_DRV_SetSrcAddr(DMA_ADC1_CHANNEL, (uint32_t)(&(ADC1->RDR[0])), (uint32_t)(&(ADC1->RDR[ADC1_CHANNEL_NUM]))); /*! 由于需要读取的源地址为ADC0的RDR0~RDR3寄存器，每个寄存器占四个字节，程序需要
                                                                                             读取每个寄存器的低位两个字节，此处需要修改DMA源地址的结束地址 */
    DMA_DRV_SetSrcOffset(DMA_ADC1_CHANNEL, 4);                                                      /*! DMA_TRANSFER_PERIPH2MEM类型的DMA只能传输一个固定的寄存器地址，此处修改偏移量
                                                                                             为4，读取完一个寄存器后地址加4，指向下一个寄存器，实现多个寄存器的连续读取*/
    DMA_DRV_SetCircularMode(DMA_ADC1_CHANNEL, true);                                                /*! 打开DMA循环模式 */
    DMA_DRV_StartChannel(DMA_ADC1_CHANNEL);                                                         /*! 使能DMA通道 */
}

/*!
 * @brief DMA初始化
 *
 * @param[in]  none
 *
 * @return none
 */
void DMA_Init(void)
{
    DMA_DRV_Init(&g_dma_state, NULL, NULL, NULL);
    
    DMA_DRV_ChannelInit(&g_dma_adc0_chn_state , &s_Adc0DmaChConfig);
    DMA_DRV_ChannelInit(&g_dma_adc1_chn_state , &s_Adc1DmaChConfig);
    DMA_DRV_ChannelInit(&g_dma_i2c_txchn_state, &s_I2cMasterTxDmaChConfig);
    DMA_DRV_ChannelInit(&g_dma_spi_txchn_state, &s_SpiMasterRxDmaChConfig);
    DMA_DRV_ChannelInit(&g_dma_spi_rxchn_state, &s_SpiMasterTxDmaChConfig);
}

/* =================================   EOF  ================================= */
