/**
  ******************************************************************************
  * @file    main.c
  * @author  AE Team
  * @version 1.0
  * @date    2024-08-15
  * @brief  使用示波器观察 DAC_CH1(PB00) 的波形。
  *
  * @note    硬件平台：CW32L012_StartKit_V1.0
  *          接线说明：None
  *
  ******************************************************************************
  * @attention
  *  
  *
  * 代码许可和免责信息
  * 武汉芯源半导体有限公司授予您使用所有编程代码示例的非专属的版权许可，您可以由此
  * 生成根据您的特定需要而定制的相似功能。根据不能被排除的任何法定保证，武汉芯源半
  * 导体有限公司及其程序开发商和供应商对程序或技术支持（如果有）不提供任何明示或暗
  * 含的保证或条件，包括但不限于暗含的有关适销性、适用于某种特定用途和非侵权的保证
  * 或条件。
  * 无论何种情形，武汉芯源半导体有限公司及其程序开发商或供应商均不对下列各项负责，
  * 即使被告知其发生的可能性时，也是如此：数据的丢失或损坏；直接的、特别的、附带的
  * 或间接的损害，或任何后果性经济损害；或利润、业务、收入、商誉或预期可节省金额的
  * 损失。
  * 某些司法辖区不允许对直接的、附带的或后果性的损害有任何的排除或限制，因此某些或
  * 全部上述排除或限制可能并不适用于您。
  *
  ******************************************************************************
  */


/******************************************************************************/
/* Include files                                                              */
/******************************************************************************/
#include "cw32l012_cordic.h"
#include "cw32l012_sysctrl.h"
#include "cw32l012_dac.h"
#include "cw32l012_dma.h"
#include "cw32l012_btim.h"


/******************************************************************************/
/* Local pre-processor symbols/macros ('#define')                             */
/******************************************************************************/

/******************************************************************************/
/* Global variable definitions (declared in header file with 'extern')        */
/******************************************************************************/

/******************************************************************************/
/* Local type definitions ('typedef')                                         */
/******************************************************************************/

/******************************************************************************/
/* Local function prototypes ('static')                                       */
/******************************************************************************/

/******************************************************************************/
/* Local variable definitions ('static')                                      */
/******************************************************************************/

/******************************************************************************/
/* Local pre-processor symbols/macros ('#define')                             */
/******************************************************************************/

/******************************************************************************/
/* Function implementation - global ('extern') and local ('static')           */
/******************************************************************************/
void DAC_Config(void);
void DMA_Config(void);
void BTIM1_Config(void);

uint16_t point[2000] = {0};

/*******************************************************************************
 ** \brief  Main function of project
 **
 ** \return uint32_t return value, if needed
 **
 **
 ******************************************************************************/
int main()
{    
	SYSCTRL_HSI_Enable(SYSCTRL_HSIOSC_DIV1);//96M
	
    cordic_init_t init = {
        .func = CORDIC_FUNC_SIN,  // 选择正弦函数
        .scale = 0,              // 不使用扩展范围
        .format = CORDIC_FORMAT_Q1_15, // 使用q1.15格式
        .iter = CORDIC_ITER_20,  // 迭代次数
        .comp = 1,               // 硬件补偿伸缩因子
        .ie = 0,                 // 禁用中断
        .dmaeoc = 0,             // 禁用DMA
        .dmaidle = 0             // 禁用DMA空闲
    };
    
   
    // 初始化CORDIC模块
    CORDIC_Init(&init);
	
	int32_t angle = 0;
	int32_t result = 0;
	float temp = 0.0f;
	float angle_pai = -1.0f;//-Π
	
	for(uint16_t i=0;i<2000;i++)
	{
		angle = float_to_q1_15(angle_pai);   // 0.25 Q1.15: 0x2000, 即：PI/4
        CW_CORDIC->Z = angle; // 写入Z寄存器启动运算
    
        // 等待运算完成
        while (!CORDIC_GetStatus().eoc);  //运算完成标志硬件置1，读取运算结果硬件清0
		
		result = CW_CORDIC->Y; // 正弦结果在Y寄存器  Q1.15格式
		
		result = result&0xFFFF;
		
		if(result&0x8000)
		{
			//angle是[-Π,0)，Y的bit15是1，Y是补码[32768,65535]=[0x8000,0xFFFF],原码：[-32768,-1]
			result = result - 65536;//计算负数的原码
		}
		else
		{
			//angle是[0,Π]，Y的bit15是0，Y是补码 [0    ,32767]=[0x0000,0x7FFF],原码：[0,32767]
		}
		temp = q1_15_to_float(result);//Q1.15格式转成0~1之间的浮点数
		
		temp = (temp+1) / 2;//temp + 1是偏置，把[-1,1]向上移至[0，2], /2是把[0,2]归一化到[0,1]
		point[i] = (uint16_t)(4095*temp);
		
		angle_pai += 0.001;//2/2000 = 0.001，[-Π,Π],[-1,1],2000个点,2/2000 = 0.001
	}
	
    DAC_Config();
	
	DMA_Config();
	
	BTIM1_Config();
	
    while(1)
	{

	}
}

void DAC_Config(void)
{
    DAC_InitTypeDef DAC_InitStruct;
    
    __SYSCTRL_DAC_CLK_ENABLE();    // 开DAC外设时钟
    __SYSCTRL_GPIOB_CLK_ENABLE();  // 开GPIOB外设时钟
    
    AFx_DACOUT1_PB00();    // PB00为DAC通道1的输出
    
    DAC_DeInit();
    
    DAC_InitStruct.DAC_ChannelState = DAC_CHANNEL_ENABLE;//通道使能
    DAC_InitStruct.DAC_DMAState = DAC_DMA_ENABLE;       // 触发DMA使能
    DAC_InitStruct.DAC_DMAUnderflowState = DAC_DMA_UNDERFLOW_DISABLE;  // DMA中断关闭
    DAC_InitStruct.DAC_TriangleAmplitude = DAC_TriangleAmplitude_4095; //
    DAC_InitStruct.DAC_TriggerSource = DAC_TRIG_BTIM1_Trgo;    // BTIM1触发
    DAC_InitStruct.DAC_TriggerState = DAC_TRIGGER_ENABLE;//TEN1 = 1，外部触发DAC使能
    DAC_InitStruct.DAC_WaveformMode = DAC_WAVE_DISABLE;    // 禁止生成波
    DAC_Init(DAC_CHANNEL_1, &DAC_InitStruct);
     
    // 通道1输出到PB00使能
    DAC_ChannelOutCmd(DAC_CHANNEL_1, ENABLE);
}

void BTIM1_Config(void)
{
	__SYSCTRL_BTIM123_CLK_ENABLE();
	
	BTIM_TimeBaseInitTypeDef  BTIM_InitStruct ={0};   
	
	// 初始化BTIM1
    BTIM_InitStruct.BTIM_CountMode = BTIM_COUNT_MODE_REPETITIVE;
    BTIM_InitStruct.BTIM_Mode = BTIM_MODE_TIMER;
    BTIM_InitStruct.BTIM_Prescaler = 96 - 1;   //  预分频系数95, 96分频，96MHz/(95+1)= 1MHz        
    BTIM_InitStruct.BTIM_Period = 1 -1;    // 溢出频率为1M
    
    BTIM_TimeBaseInit(CW_BTIM1, &BTIM_InitStruct);
    
    BTIM_MasterOutputTriggerConfig(CW_BTIM1, BTIM_MASTER_OUTPUT_TRIGGER_OVERFLOW);
	
	BTIM_Cmd(CW_BTIM1, ENABLE);
}

void DMA_Config(void)
{
	__SYSCTRL_DMA_CLK_ENABLE();
	
	DMA_InitTypeDef DMA_InitStruct = {0};
    
    DMA_InitStruct.BlockCount = 1;
    DMA_InitStruct.TransferCount =  2000;
    DMA_InitStruct.DataSize = DMA_DATA_SIZE_16BITS;
    DMA_InitStruct.DstAddress = (uint32_t)&CW_DAC->DHR12R1;
    DMA_InitStruct.DstIncrement = DMA_ADDRESS_FIXED;
    DMA_InitStruct.RestartEnable = TRUE;
    DMA_InitStruct.SrcAddress = (uint32_t)point;
    DMA_InitStruct.SrcIncrement = DMA_ADDRESS_INCREMENT;
    DMA_InitStruct.TransferMode = DMA_MODE_BLOCK;
    DMA_InitStruct.TriggerSource = DMA_TRIGGER_SRC_DAC1_DHR_OVF;//采用软件触发，硬件触发源无意义
    DMA_InitStruct.TriggerType = DMA_TRIGGER_HARDWARE;
    
    // 初始化DMA
    DMA_Init(DMA_CHANNEL_1, &DMA_InitStruct);
    
    // 使能DMA
    DMA_Cmd(DMA_CHANNEL_1, ENABLE);
}
/*******************************************************************************
 ** EOF (not truncated)
 ******************************************************************************/
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* USER CODE BEGIN */
    /* User can add his own implementation to report the file name and line number */
    printf("Wrong parameters value: file %s on line %d\r\n", file, line);
    /* USER CODE END */
}
#endif /* USE_FULL_ASSERT */


/************************ (C) COPYRIGHT SIYIMicro *****END OF FILE*************/
