/********************************************************************************
 * @file    TWI_Slave_DMA.c
 * @author  SOC AE Team
 * @version V1.1
 * @date    2025-06-27
 * @brief   TWI0作为从机，TWI1作为主机，TWI0使用DMA向TWI1发送和接收数据。（主从机模式请在宏定义进行选择，TWI_Mode=0为主机代码，TWI_Mode=1为从机代码）
 *          主机需复位操作
 *******************************************************************************/
#include "sc32_conf.h"
#include "Function_Init.h"

/* 选择主从机代码 */
#define TWI_Mode 0
 uint8_t Slave_DMA_TWI1_SendData[16] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff};
 uint8_t Slave_DMA_TWI0_SendData[16] = {0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x2f};


#if (TWI_Mode == 0)
  static volatile FlagStatus TWI1_Flag = RESET;
  static uint8_t TWI1_Num = 0;
  uint8_t Slave_DMA_TWI1_ReceiveData[16];  
#elif(TWI_Mode == 1)
  static volatile FlagStatus DMA0_Flag = RESET, DMA1_Flag = RESET;
  uint8_t Slave_DMA_TWI0_ReceiveData[16]; 
#endif

void TWI_Slave_DMA_Function(void)
{

#if (TWI_Mode == 0)
 #if defined(SC32f12xx)
  GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT_PP;
  GPIO_Init(GPIOB, &GPIO_InitStruct);
 #elif defined(SC32f10xx)
  GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT_PP;
  GPIO_Init(GPIOA, &GPIO_InitStruct);

 #endif  
 
  TWI_InitTypeDef TWI_InitStruct; //定义TWI初始化结构体变量
  
  RCC_APB1Cmd(ENABLE);  //TWI1外设挂载在APB1时钟上
#if defined(SC32f10xx)||defined(SC32f12xx)
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TWI1, ENABLE);
#endif
  /* 结构体成员初始化 */
  TWI_StructInit(&TWI_InitStruct);
  
  /* TWI1配置为主机*/
  {
    TWI_InitStruct.TWI_Ack = TWI_Ack_Enable;	//回应ACK
#if defined(SC32f10xx)||defined(SC32f12xx)
    TWI_InitStruct.TWI_Prescaler = TWI_PRESCALER_64;
#endif
    TWI_InitStruct.TWI_Stretch = TWI_Stretch_Enable;
    /*  根据结构体配置初始化串口 */
    TWI_Init(TWI1, &TWI_InitStruct);
   

#if defined(SC32f10xx)||defined(SC32f12xx)
    /* 使能TWI中断 */
    TWI_ITConfig(TWI1, TWI_IT_INT, ENABLE);
    NVIC_EnableIRQ(TWI1_IRQn);
#endif
    /* 使能接收发送口 */
    TWI_Cmd(TWI1, ENABLE);
  }
#elif(TWI_Mode == 1)
  
  TWI_InitTypeDef TWI_InitStruct; //定义TWI初始化结构体变量
  DMA_InitTypeDef DMA_InitStruct; //定义DMA初始化结构体变量
  
  /* 使能DMA和TWI0的时钟 */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA, ENABLE);
  RCC_APB0Cmd(ENABLE);  //TWI0外设挂载在APB0时钟上
#if defined(SC32f10xx)||defined(SC32f12xx)
  RCC_APB0PeriphClockCmd(RCC_APB0Periph_TWI0, ENABLE);
#endif
  /* 结构体成员初始化 */
  TWI_StructInit(&TWI_InitStruct);
  DMA_StructInit(&DMA_InitStruct);
  
  /* TWI0从机*/
  {
    /* 配置TWI0作为从机 */
    TWI_InitStruct.TWI_Ack = TWI_Ack_Enable;	//回应ACK
    TWI_InitStruct.TWI_GeneralCall = TWI_GeneralCall_Disable;	//不响应通用地址
    TWI_InitStruct.TWI_SlaveAdress = 0x12;	//配置从机地址
    TWI_InitStruct.TWI_Stretch = TWI_Stretch_Enable;
    /*  根据结构体配置初始化串口 */
    TWI_Init(TWI0, &TWI_InitStruct);
    /* 使能TWI中断 */
#if defined(SC32f10xx)||defined(SC32f12xx)
    TWI_ITConfig(TWI0, TWI_IT_INT, ENABLE);
    NVIC_EnableIRQ(TWI0_IRQn);
#endif
    /* 使能TWI DMA */
    TWI_DMACmd(TWI0, TWI_DMAReq_TX, ENABLE);
#if defined(SC32f12xx)
    TWI_PinRemapConfig(TWI0,TWI_PinRemap_A);
#endif
    /* 使能接收发送口 */
    TWI_Cmd(TWI0, ENABLE);
  }
  
  /* TWI0从机DMA发送配置 */
  {
    DMA_InitStruct.DMA_BufferSize = 16;	//DMA搬运数量为16个
    DMA_InitStruct.DMA_CircularMode = DMA_CircularMode_Enable;	//关闭循环模式
    DMA_InitStruct.DMA_DataSize = DMA_DataSize_Byte;	//传输宽度为字节
    DMA_InitStruct.DMA_SourceMode = DMA_SourceMode_INC_CIRC;	//源地址循环递增
    DMA_InitStruct.DMA_TargetMode = DMA_TargetMode_FIXED;	//目标地址固定
    DMA_InitStruct.DMA_SrcAddress = (uint32_t)Slave_DMA_TWI0_SendData;
    DMA_InitStruct.DMA_DstAddress = (uint32_t)&TWI0->TWI_DATA;
#if defined(SC32f10xx)||defined(SC32f12xx)
    DMA_InitStruct.DMA_Request = DMA_Request_TWI0_TX;	//TWI0 发送触发DMA0
#endif
    DMA_InitStruct.DMA_Priority = DMA_Priority_HIGH;	//设置优先级为高
    DMA_Init(DMA0, &DMA_InitStruct);
    DMA_Cmd(DMA0, ENABLE);	//使能DMA0
  }
  
  /* TWI0从机DMA接收配置 */
  {
    DMA_InitStruct.DMA_BufferSize = 16;	//DMA搬运数量为16个
    DMA_InitStruct.DMA_CircularMode = DMA_CircularMode_Enable;	//关闭循环模式
    DMA_InitStruct.DMA_DataSize = DMA_DataSize_Byte;	//传输宽度为字节
    DMA_InitStruct.DMA_SourceMode = DMA_SourceMode_FIXED;	//源地址固定
    DMA_InitStruct.DMA_TargetMode = DMA_TargetMode_INC_CIRC;	//目标地址循环递增
    DMA_InitStruct.DMA_SrcAddress = (uint32_t)&TWI0->TWI_DATA;
    DMA_InitStruct.DMA_DstAddress = (uint32_t)Slave_DMA_TWI0_ReceiveData;
#if defined(SC32f10xx)||defined(SC32f12xx)
    DMA_InitStruct.DMA_Request = DMA_Request_TWI0_RX;	//TWI0 发送触发DMA1
#endif
    DMA_InitStruct.DMA_Priority = DMA_Priority_HIGH;	//设置优先级为高
    DMA_Init(DMA1, &DMA_InitStruct);
    DMA_Cmd(DMA1, ENABLE);	//使能DMA1
  }

#endif
  
  while(1)
  {
#if (TWI_Mode == 0)
    
    /* 主机发送 */
    TWI_GenerateSTART(TWI1, ENABLE);
    {
      uint32_t delay_time = 100;
      while(delay_time--);
    }
    while(TWI1_Flag == RESET);	//等待起始信号发送完成
    TWI1_Flag = RESET;
    
    TWI_Send7bitAddress(TWI1, 0x12, TWI_Command_Write);
    while(TWI1_Flag == RESET);	//等待地址发送完成
    TWI1_Flag = RESET;
    
    while(TWI1_Num < 16)
    {
      /* TWI1没有DMA，需要手动发送数据 */
      TWI_SendData(TWI1, Slave_DMA_TWI1_SendData[TWI1_Num]);
      while(TWI1_Flag == RESET);	//等待数据发送完成
      TWI1_Flag = RESET;
      TWI1_Num ++;
    }
    TWI1_Num = 0;
    TWI_GenerateSTOP(TWI1, ENABLE);
    while(TWI_GetStateMachine(TWI1) != TWI_Master_Idle);
    printf("TWI1主机发送数据成功！\r\n");
    
    {
      uint32_t delay_time = 5000;
      while(delay_time--);
    }
    
    /* 主机接收 */
    TWI_AcknowledgeConfig(TWI1, ENABLE);
    TWI_GenerateSTART(TWI1, ENABLE);
    {
      uint32_t delay_time = 100;
      while(delay_time--);
    }
    while(TWI1_Flag == RESET);	//等待起始信号发送完成
    TWI1_Flag = RESET;
    
    TWI_Send7bitAddress(TWI1, 0x12, TWI_Command_Read);
    while(TWI1_Flag == RESET);	//等待起始信号发送完成
    TWI1_Flag = RESET;
    
    while(TWI1_Num < 16)
    {
      
      while(TWI1_Flag == RESET);	//等待起始信号发送完成
      TWI1_Flag = RESET;
      /* TWI1没有DMA，需要手动接收数据 */
      Slave_DMA_TWI1_ReceiveData[TWI1_Num] = TWI_ReceiveData(TWI1);
      TWI1_Num ++;
      if(TWI1_Num == 15)
      {
        TWI_AcknowledgeConfig(TWI1, DISABLE);
      }
      //TWI1_Flag = RESET;
    }
    TWI1_Num = 0;
    
    TWI_GenerateSTOP(TWI1, ENABLE);
    while(TWI_GetStateMachine(TWI1) != TWI_Master_Idle);
    for(int i=0 ;i <= 15 ;i++)	printf("TWI1主机接收到的数据是 %x。\r\n",Slave_DMA_TWI1_ReceiveData[i]);
     TWI_AcknowledgeConfig(TWI1, ENABLE);
    {
      uint32_t delay_time = 100000;
      while(delay_time--);
    }	
#elif(TWI_Mode == 1)
    /* 从机接收 */
    TWI_SetNbytes(TWI0, 16);
    DMA_SetCurrDataCounter(DMA1, 16);
    TWI_DMACmd(TWI0, TWI_DMAReq_RX, DISABLE);
    TWI_DMACmd(TWI0, TWI_DMAReq_RX, ENABLE);
    while(TWI_GetStateMachine(TWI0) != TWI_Slave_ReceivedaData);  //等待从机接收状态
    while(DMA_GetFlagStatus(DMA1, DMA_FLAG_TCIF) == RESET);
    DMA_ClearFlag(DMA1, DMA_FLAG_TCIF);
    while(TWI_GetStateMachine(TWI0) != TWI_Slave_Idle);  //等待从机空闲状态
    for(int i=0 ;i <= 15 ;i++)	printf("TWI0从机接收到的数据是 %x。\r\n",Slave_DMA_TWI0_ReceiveData[i]);
    /* 从机发送 */
    /* TWI使用DMA传输时需要配置Nbyte个数 */
    TWI_SetNbytes(TWI0, 16);
    DMA_SetCurrDataCounter(DMA0, 16);
		 
    TWI_DMACmd(TWI0, TWI_DMAReq_TX, DISABLE);
    TWI_DMACmd(TWI0, TWI_DMAReq_TX, ENABLE);
		while(TWI_GetStateMachine(TWI0) != TWI_Slave_SendData);  //等待从机发送状态
		DMA_SoftwareTrigger(DMA0);	//软件触发第一次搬运
   
    
    while(DMA_GetFlagStatus(DMA0, DMA_FLAG_TCIF) == RESET);
    DMA_ClearFlag(DMA0, DMA_FLAG_TCIF);
    printf("TWI0从机发送数据成功！\r\n");
    
#endif
    
  }
}

void TWI_Slave_DMA_TWI0Handler(void)
{
#if (TWI_Mode == 1)
#if defined(SC32f10xx)||defined(SC32f12xx)
  if(TWI_GetFlagStatus(TWI0, TWI_FLAG_TWIF) == SET)
  {
    TWI_ClearFlag(TWI0, TWI_FLAG_TWIF);
  }

#endif
#endif
}



void TWI_Slave_DMA_TWI1Handler(void)
{
#if (TWI_Mode == 0)
#if defined(SC32f10xx)||defined(SC32f12xx)
  if(TWI_GetFlagStatus(TWI1, TWI_FLAG_TWIF) == SET)
  {
    TWI1_Flag = SET;
    TWI_ClearFlag(TWI1, TWI_FLAG_TWIF);
  }

#endif
#endif
}


