CH32X035_FreeRTOS/src/app_led1w.c

122 lines
3.7 KiB
C

#include <stdint.h>
/* SDK */
#include "ch32x035.h"
#include "ch32x035_dma.h"
#include "ch32x035_gpio.h"
#include "ch32x035_spi.h"
/* Private */
#include "app_led1w.h"
#define APP_LED1W_MAXIMUM_LEDS 64
#define APP_LED1W_ZERO_PADDING 32 /* Additional padding for a RESET condition (50uS) */
#define APP_LED1W_SPI_0B (0x08U) /* 4'b1000 */
#define APP_LED1W_SPI_1B (0x0EU) /* 4'b1110 */
/* SPI buffer to store waveform data */
static uint8_t s_led1w_spi_buf[APP_LED1W_MAXIMUM_LEDS * 3 * 8 / 2 + APP_LED1W_ZERO_PADDING];
static void app_led1w_encode(const uint8_t *data, uint16_t len);
void app_led1w_init(void) {
/* Enable DMA and SPI clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Initialize SPI peripheral */
SPI_InitTypeDef spi_init;
/*
* 48MHz / 16 = 3MHz
* Timing:
* T0H: 334ns
* T0L: 1002ns
* T1H: 1002ns
* T1L: 334ns
*/
spi_init.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
spi_init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
spi_init.SPI_Mode = SPI_Mode_Master;
spi_init.SPI_CPOL = SPI_CPOL_Low;
spi_init.SPI_CPHA = SPI_CPHA_1Edge;
spi_init.SPI_NSS = SPI_NSS_Soft;
spi_init.SPI_FirstBit = SPI_FirstBit_MSB;
spi_init.SPI_DataSize = SPI_DataSize_8b;
SPI_Init(SPI1, &spi_init);
GPIO_InitTypeDef gpio_init;
gpio_init.GPIO_Pin = GPIO_Pin_7;
gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_init);
}
int app_led1w_write(uint8_t *data, uint16_t led_count) {
uint16_t byte_count = led_count * 3 * 8 / 2;
if ((byte_count + APP_LED1W_ZERO_PADDING) > sizeof(s_led1w_spi_buf)) {
return -1;
}
app_led1w_encode(data, led_count * 3);
/* Initialize DMA peripheral */
DMA_InitTypeDef dma_init;
dma_init.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DATAR;
dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma_init.DMA_MemoryBaseAddr = (uint32_t)s_led1w_spi_buf;
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma_init.DMA_DIR = DMA_DIR_PeripheralDST;
dma_init.DMA_Mode = DMA_Mode_Normal;
dma_init.DMA_Priority = DMA_Priority_Medium;
dma_init.DMA_M2M = DMA_M2M_Disable;
dma_init.DMA_BufferSize = byte_count + APP_LED1W_ZERO_PADDING;
DMA_Init(DMA1_Channel3, &dma_init);
/* Enable SPI TX DMA request generation */
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
DMA_Cmd(DMA1_Channel3, ENABLE);
NVIC_EnableIRQ(DMA1_Channel3_IRQn);
SPI_Cmd(SPI1, ENABLE);
return 0;
}
static void app_led1w_encode(const uint8_t *data, uint16_t len) {
for (uint32_t i = 0; i < APP_LED1W_ZERO_PADDING; i++) {
s_led1w_spi_buf[i] = 0x00;
}
for (uint16_t i = 0; i < len + 0; i++) {
uint16_t buf_index = i * 4 + APP_LED1W_ZERO_PADDING; // Add 0 padding
for (uint8_t j = 0; j < 4; j++) {
uint8_t bit_offset_l = (3 - j) * 2;
uint8_t bit_offset_h = (3 - j) * 2 + 1;
uint8_t buf_payload = (data[i] >> bit_offset_l & 0x01U) ? APP_LED1W_SPI_1B : APP_LED1W_SPI_0B;
buf_payload |= (((data[i] >> bit_offset_h) & 0x01U) ? APP_LED1W_SPI_1B : APP_LED1W_SPI_0B) << 4U;
s_led1w_spi_buf[buf_index + j] = buf_payload;
}
}
}
void app_led1w_irq_handler(void) {
}