/**
 * @file oled_spi_dma.c
 * @brief This is oled spi dma file
 * @version 1.0
 * @date 2023-11-21
 *
 * @copyright Copyright 2021-2023 xunfeng Inc. All Rights Reserved.
 *
 * OLED SPI用到SCL Dout(MOSI) DC(写指令/数据) 用到的硬件SPI线只有两根SCL和MOSI，在写指令/数据的时候需要自己去拉DC
 */


#include "spi.h"
#include "dma.h"
#include "tkl_spi.h"
#include "tal_log.h"
#include "tal_sw_timer.h"
#include "tuya_cloud_types.h"
#include "mcu_phy_bumbee.h"

#include "oled_spi_dma.h"


static hal_spi_t spi_ptr;
static spi_Cfg_t spim_cfg;
static HAL_DMA_t dma_cfg;
static oled_send_t  oled_send;



STATIC TIMER_ID spi_test_timer_id = NULL;
STATIC VOID_T spi_test_timeout_handler(TIMER_ID timer_id, VOID_T *arg)
{
	static uint8_t test=0;
	TAL_PR_INFO("dma send test=%d!!!\r\n",test);
	oled_spi_dma_send(OLED_DC_TYPE_CMD, &test, 1);
    test++;

}


/**
 * @brief oled_dma_IRQHnadlerCb dma中断处理回调
 *
 * @param[in] ch: dma通道
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
static void oled_dma_IRQHnadlerCb (DMA_CH_t ch)
{
	oled_send.dma_status = OLED_DMA_IDLE;
	TAL_PR_INFO("dma send complete!!!\r\n");
}

/**
 * @brief DMA状态设置与获取
 *
 * @param[in] param: none
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
oled_dma_status_t oled_dma_status_get()
{
	return oled_send.dma_status;
}

void oled_dma_status_set(oled_dma_status_t status)
{
	oled_send.dma_status = status;
}

/**
 * @brief oled_spi_dma_init 硬件SPI DMA 驱动OLED初始化
 *
 * @param[in] param: none
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
int32_t oled_spi_dma_init()
{
	int32_t ret = PPlus_SUCCESS;

	/* DMA 初始化使能 */
	hal_dma_init();
	
	spi_ptr.spi_index = SPI1;
	hal_spi_init(spi_ptr.spi_index);	

	spim_cfg.MOSI = OLED_SDA_PIN;
	spim_cfg.sclk_pin = OLED_SCL_PIN;
	spim_cfg.baudrate = 7000000; 		/* 时钟频率 */
	spim_cfg.spi_tmod = SPI_TXD;		/* 只发送 */
	spim_cfg.spi_scmod = SPI_MODE0;		/* SPI时钟极性及相位设置 */
  	spim_cfg.int_mode = false;			/* SPI中断？？？ */
  	spim_cfg.force_cs = true;			/* 片选信号 */
	spim_cfg.spi_dfsmod = SPI_1BYTE;	
  	spim_cfg.evt_handler = NULL;	

	ret = hal_spi_bus_init(&spi_ptr, spim_cfg);

	if(ret != PPlus_SUCCESS)
	{
		TAL_PR_ERR("oled spi init err!!!\r\n");
		return ret;
	}

	/* DMA设置 */
	dma_cfg.dma_channel = DMA_CH_0;
  	dma_cfg.evt_handler = oled_dma_IRQHnadlerCb;	/* 中断回调 hal_DMA_IRQHandler */
	ret = hal_dma_init_channel(dma_cfg);

	if(ret != PPlus_SUCCESS)
	{
		TAL_PR_ERR("oled dma init err!!!\r\n");
		return ret;
	}

	/* 创建一个SPI DMA测试定时器 */
	TAL_PR_INFO("create spi test timer!!!\r\n");
	tal_sw_timer_create(spi_test_timeout_handler, NULL, &spi_test_timer_id);
	tal_sw_timer_start(spi_test_timer_id,2000,TAL_TIMER_CYCLE);

	return ret;
}


/**
 * @brief oled_spi_dma_send oled spi dma发送数据
 *
 * @param[in] ch: dma通道
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */ 
int32_t oled_spi_dma_send(oled_dc_type_t type, uint8_t *txbuf, uint16_t txlen)
{
	int32_t ret = PPlus_SUCCESS;
		
	if(oled_dma_status_get() == OLED_DMA_IDLE)
	{
		oled_dma_status_set(OLED_DMA_BUSY);

		/* 根据发送是命令或者数据设置DC电平 */
		if(type == OLED_DC_TYPE_CMD)
		{
			OLED_DC_Clr();
		}
		else
		{
			OLED_DC_Set();
		}

		hal_spi_dma_set(&spi_ptr,true,false);
		ret = hal_spi_transmit(&spi_ptr,SPI_TXD,txbuf,NULL,txlen,0);	/* 注意此处长度  DMA_GET_MAX_TRANSPORT_SIZE */

		if(ret != PPlus_SUCCESS)
		{
			TAL_PR_ERR("oled dma send err!!!\r\n");
			return ret;
		}

	}
	else
	{
		TAL_PR_ERR("oled dma send busy!!!\r\n");
		ret = PPlus_ERR_BUSY;
		return ret;

	}	
		
	return ret;
}


