generated from Embedded_Projects/CH32X035_Template
122 lines
3.7 KiB
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) {
|
|
|
|
} |