working example

pull/2666/head
Jack Humbert 6 years ago
parent d233737c95
commit af6107bee8

@ -1,253 +1,156 @@
/** /*
* @file ws2812.c * LEDDriver.c
* @author Austin Glaser <austin.glaser@gmail.com>
* @brief WS2812 LED driver
*
* Copyright (C) 2016 Austin Glaser
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
* *
* @todo Put in names and descriptions of variables which need to be defined to use this file * Created on: Aug 26, 2013
* * Author: Omri Iluz
* @addtogroup WS2812
* @{
*/ */
/* --- PRIVATE DEPENDENCIES ------------------------------------------------- */
// This Driver
#include "ws2812.h" #include "ws2812.h"
#include "stdlib.h"
static uint8_t *fb;
static int sLeds;
static stm32_gpio_t *sPort;
static uint32_t sMask;
uint8_t* dma_source;
void setColor(uint8_t color, uint8_t *buf,uint32_t mask){
int i;
for (i=0;i<8;i++){
buf[i]=((color<<i)&0b10000000?0x0:mask);
}
}
// Standard void setColorRGB(Color c, uint8_t *buf, uint32_t mask){
#include <stdint.h> setColor(c.G,buf, mask);
setColor(c.R,buf+8, mask);
// ChibiOS setColor(c.B,buf+16, mask);
#include "ch.h" }
#include "hal.h"
// Application
#include "board.h"
#include "util.h"
/* --- CONFIGURATION CHECK -------------------------------------------------- */
#if !defined(WS2812_LED_N)
#error WS2812 LED chain length not specified
#elif WS2812_LED_N <= 0
#error WS2812 LED chain length set to invalid value
#endif
#if !defined(WS2812_TIM_N)
#error WS2812 timer not specified
#endif
// values for these might be found in table 14 in DM00058181 (STM32F303)
#if defined(STM32F2XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32F7XX)
#if WS2812_TIM_N <= 2
#define WS2812_AF 1
#elif WS2812_TIM_N <= 5
#define WS2812_AF 2
#elif WS2812_TIM_N <= 11
#define WS2812_AF 3
#endif
#elif !defined(WS2812_AF)
#error WS2812_AF timer alternate function not specified
#endif
#if !defined(WS2812_TIM_CH)
#error WS2812 timer channel not specified
#elif WS2812_TIM_CH >= 4
#error WS2812 timer channel set to invalid value
#endif
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
//#define WS2812_PWM_FREQUENCY (STM32_SYSCLK/2) /**< Clock frequency of PWM */
#define WS2812_PWM_FREQUENCY (72000000) /**< Clock frequency of PWM */
//#define WS2812_PWM_PERIOD (WS2812_PWM_FREQUENCY/800000) /**< Clock period in ticks. 90/(72 MHz) = 1.25 uS (as per datasheet) */
#define WS2812_PWM_PERIOD (90) /**< Clock period in ticks. 90/(72 MHz) = 1.25 uS (as per datasheet) */
/**
* @brief Number of bit-periods to hold the data line low at the end of a frame
*
* The reset period for each frame must be at least 50 uS; so we add in 50 bit-times
* of zeroes at the end. (50 bits)*(1.25 uS/bit) = 62.5 uS, which gives us some
* slack in the timing requirements
*/
#define WS2812_RESET_BIT_N (50)
#define WS2812_COLOR_BIT_N (WS2812_LED_N*24) /**< Number of data bits */
#define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */
/**
* @brief High period for a zero, in ticks
*
* Per the datasheet:
* - T0H: 0.200 uS to 0.500 uS, inclusive
* - T0L: 0.650 uS to 0.950 uS, inclusive
*
* With a duty cycle of 22 ticks, we have a high period of 22/(72 MHz) = 3.06 uS, and
* a low period of (90 - 22)/(72 MHz) = 9.44 uS. These values are within the allowable
* bounds, and intentionally skewed as far to the low duty-cycle side as possible
*/
//#define WS2812_DUTYCYCLE_0 (WS2812_PWM_FREQUENCY/(1000000000/350))
#define WS2812_DUTYCYCLE_0 (22)
/**
* @brief High period for a one, in ticks
*
* Per the datasheet:
* - T0H: 0.550 uS to 0.850 uS, inclusive
* - T0L: 0.450 uS to 0.750 uS, inclusive
*
* With a duty cycle of 56 ticks, we have a high period of 56/(72 MHz) = 7.68 uS, and
* a low period of (90 - 56)/(72 MHz) = 4.72 uS. These values are within the allowable
* bounds, and intentionally skewed as far to the high duty-cycle side as possible
*/
//#define WS2812_DUTYCYCLE_1 (WS2812_PWM_FREQUENCY/(1000000000/800))
#define WS2812_DUTYCYCLE_1 (56)
/* --- PRIVATE MACROS ------------------------------------------------------- */
/**
* @brief Generates a reference to a numbered PWM driver
*
* @param[in] n: The driver (timer) number
*
* @return A reference to the driver
*/
#define PWMD(n) CONCAT_EXPANDED_SYMBOLS(PWMD, n)
#define WS2812_PWMD PWMD(WS2812_TIM_N) /**< The PWM driver to use for the LED chain */
/**
* @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given bit
*
* @param[in] led: The led index [0, @ref WS2812_LED_N)
* @param[in] byte: The byte number [0, 2]
* @param[in] bit: The bit number [0, 7]
*
* @return The bit index
*/
#define WS2812_BIT(led, byte, bit) (24*(led) + 8*(byte) + (7 - (bit)))
/**
* @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit
*
* @note The red byte is the middle byte in the color packet
*
* @param[in] led: The led index [0, @ref WS2812_LED_N)
* @param[in] bit: The bit number [0, 7]
*
* @return The bit index
*/
#define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 1, (bit))
/**
* @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit
*
* @note The red byte is the first byte in the color packet
*
* @param[in] led: The led index [0, @ref WS2812_LED_N)
* @param[in] bit: The bit number [0, 7]
*
* @return The bit index
*/
#define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 0, (bit))
/** /**
* @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit * @brief Initialize Led Driver
* * @details Initialize the Led Driver based on parameters.
* @note The red byte is the last byte in the color packet * Following initialization, the frame buffer would automatically be
* * exported to the supplied port and pins in the right timing to drive
* @param[in] led: The led index [0, @ref WS2812_LED_N) * a chain of WS2812B controllers
* @param[in] bit: The bit index [0, 7] * @note The function assumes the controller is running at 72Mhz
* @note Timing is critical for WS2812. While all timing is done in hardware
* need to verify memory bandwidth is not exhausted to avoid DMA delays
*
* @param[in] leds length of the LED chain controlled by each pin
* @param[in] port which port would be used for output
* @param[in] mask Which pins would be used for output, each pin is a full chain
* @param[out] o_fb initialized frame buffer
* *
* @return The bit index
*/ */
#define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 2, (bit)) void ledDriverInit(int leds, stm32_gpio_t *port, uint32_t mask, uint8_t **o_fb) {
sLeds=leds;
/* --- PRIVATE VARIABLES ---------------------------------------------------- */ sPort=port;
sMask=mask;
static uint8_t ws2812_frame_buffer[WS2812_BIT_N]; /**< Buffer for a frame */ palSetGroupMode(port, sMask, 0, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST|PAL_STM32_PUPDR_FLOATING);
/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */ // configure pwm timers -
// timer 2 as master, active for data transmission and inactive to disable transmission during reset period (50uS)
void ws2812_init(void) // timer 3 as slave, during active time creates a 1.25 uS signal, with duty cycle controlled by frame buffer values
{ static PWMConfig pwmc2 = {72000000 / 90, /* 800Khz PWM clock frequency. 1/90 of PWMC3 */
// Initialize led frame buffer (72000000 / 90) * 0.05, /*Total period is 50ms (20FPS), including sLeds cycles + reset length for ws2812b and FB writes */
uint32_t i; NULL,
for (i = 0; i < WS2812_COLOR_BIT_N; i++) ws2812_frame_buffer[i] = WS2812_DUTYCYCLE_0; // All color bits are zero duty cycle { {PWM_OUTPUT_ACTIVE_HIGH, NULL},
for (i = 0; i < WS2812_RESET_BIT_N; i++) ws2812_frame_buffer[i + WS2812_COLOR_BIT_N] = 0; // All reset bits are zero {PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL},
// Configure PA1 as AF output {PWM_OUTPUT_DISABLED, NULL}},
//#ifdef WS2812_EXTERNAL_PULLUP TIM_CR2_MMS_2, /* master mode selection */
// palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_ALTERNATE(WS2812_AF) | PAL_STM32_OTYPE_OPENDRAIN); 0, };
//#else /* master mode selection */
palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_ALTERNATE(1)); static PWMConfig pwmc3 = {72000000,/* 72Mhz PWM clock frequency. */
//#endif 90, /* 90 cycles period (1.25 uS per period @72Mhz */
NULL,
// PWM Configuration { {PWM_OUTPUT_ACTIVE_HIGH, NULL},
#pragma GCC diagnostic ignored "-Woverride-init" // Turn off override-init warning for this struct. We use the overriding ability to set a "default" channel config {PWM_OUTPUT_ACTIVE_HIGH, NULL},
static const PWMConfig ws2812_pwm_config = { {PWM_OUTPUT_ACTIVE_HIGH, NULL},
.frequency = WS2812_PWM_FREQUENCY, {PWM_OUTPUT_ACTIVE_HIGH, NULL}},
.period = WS2812_PWM_PERIOD, 0,
.callback = NULL, 0,
.channels = { };
[0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled dma_source = chHeapAlloc(NULL, 1);
[WS2812_TIM_CH] = {.mode = PWM_OUTPUT_ACTIVE_HIGH, .callback = NULL}, // Turn on the channel we care about fb = chHeapAlloc(NULL, ((sLeds) * 24)+10);
}, *o_fb=fb;
.cr2 = 0, int j;
.dier = TIM_DIER_UDE, // DMA on update event for next period for (j = 0; j < (sLeds) * 24; j++) fb[j] = 0;
}; dma_source[0] = sMask;
#pragma GCC diagnostic pop // Restore command-line warning options // DMA stream 2, triggered by channel3 pwm signal. if FB indicates, reset output value early to indicate "0" bit to ws2812
dmaStreamAllocate(STM32_DMA1_STREAM2, 10, NULL, NULL);
// Configure DMA dmaStreamSetPeripheral(STM32_DMA1_STREAM2, &(sPort->BSRR.H.clear));
dmaStreamAllocate(WS2812_DMA_STREAM, 10, NULL, NULL); dmaStreamSetMemory0(STM32_DMA1_STREAM2, fb);
dmaStreamSetPeripheral(WS2812_DMA_STREAM, &(WS2812_PWMD.tim->CCR[WS2812_TIM_CH])); dmaStreamSetTransactionSize(STM32_DMA1_STREAM2, (sLeds) * 24);
dmaStreamSetMemory0(WS2812_DMA_STREAM, ws2812_frame_buffer); dmaStreamSetMode(
dmaStreamSetTransactionSize(WS2812_DMA_STREAM, WS2812_BIT_N); STM32_DMA1_STREAM2,
dmaStreamSetMode(WS2812_DMA_STREAM, STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_MINC | STM32_DMA_CR_PSIZE_BYTE
STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_BYTE | | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(2));
STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); // DMA stream 3, triggered by pwm update event. output high at beginning of signal
//STM32_DMA_CR_CHSEL(WS2812_DMA_CHANNEL) | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD | dmaStreamAllocate(STM32_DMA1_STREAM3, 10, NULL, NULL);
//STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); dmaStreamSetPeripheral(STM32_DMA1_STREAM3, &(sPort->BSRR.H.set));
dmaStreamSetMemory0(STM32_DMA1_STREAM3, dma_source);
// Start DMA dmaStreamSetTransactionSize(STM32_DMA1_STREAM3, 1);
dmaStreamEnable(WS2812_DMA_STREAM); dmaStreamSetMode(
STM32_DMA1_STREAM3, STM32_DMA_CR_TEIE |
// Configure PWM STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE
// NOTE: It's required that preload be enabled on the timer channel CCR register. This is currently enabled in the | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3));
// ChibiOS driver code, so we don't have to do anything special to the timer. If we did, we'd have to start the timer, // DMA stream 6, triggered by channel1 update event. reset output value late to indicate "1" bit to ws2812.
// disable counting, enable the channel, and then make whatever configuration changes we need. // always triggers but no affect if dma stream 2 already change output value to 0
pwmStart(&WS2812_PWMD, &ws2812_pwm_config); dmaStreamAllocate(STM32_DMA1_STREAM6, 10, NULL, NULL);
pwmEnableChannel(&WS2812_PWMD, WS2812_TIM_CH, 0); // Initial period is 0; output will be low until first duty cycle is DMA'd in dmaStreamSetPeripheral(STM32_DMA1_STREAM6, &(sPort->BSRR.H.clear));
dmaStreamSetMemory0(STM32_DMA1_STREAM6, dma_source);
dmaStreamSetTransactionSize(STM32_DMA1_STREAM6, 1);
dmaStreamSetMode(
STM32_DMA1_STREAM6,
STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE
| STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3));
pwmStart(&PWMD2, &pwmc2);
pwmStart(&PWMD3, &pwmc3);
// set pwm3 as slave, triggerd by pwm2 oc1 event. disables pwmd2 for synchronization.
PWMD3.tim->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2 | TIM_SMCR_TS_0;
PWMD2.tim->CR1 &= ~TIM_CR1_CEN;
// set pwm values.
// 28 (duty in ticks) / 90 (period in ticks) * 1.25uS (period in S) = 0.39 uS
pwmEnableChannel(&PWMD3, 2, 28);
// 58 (duty in ticks) / 90 (period in ticks) * 1.25uS (period in S) = 0.806 uS
pwmEnableChannel(&PWMD3, 0, 58);
// active during transfer of 90 cycles * sLeds * 24 bytes * 1/90 multiplier
pwmEnableChannel(&PWMD2, 0, 90 * sLeds * 24 / 90);
// stop and reset counters for synchronization
PWMD2.tim->CNT = 0;
// Slave (TIM3) needs to "update" immediately after master (TIM2) start in order to start in sync.
// this initial sync is crucial for the stability of the run
PWMD3.tim->CNT = 89;
PWMD3.tim->DIER |= TIM_DIER_CC3DE | TIM_DIER_CC1DE | TIM_DIER_UDE;
dmaStreamEnable(STM32_DMA1_STREAM3);
dmaStreamEnable(STM32_DMA1_STREAM6);
dmaStreamEnable(STM32_DMA1_STREAM2);
// all systems go! both timers and all channels are configured to resonate
// in complete sync without any need for CPU cycles (only DMA and timers)
// start pwm2 for system to start resonating
PWMD2.tim->CR1 |= TIM_CR1_CEN;
} }
ws2812_err_t ws2812_write_led(uint32_t led_number, uint8_t r, uint8_t g, uint8_t b) void ledDriverWaitCycle(void){
{ while (PWMD2.tim->CNT < 90 * sLeds * 24 / 90){chThdSleepMicroseconds(1);};
// Check for valid LED
if (led_number >= WS2812_LED_N) return WS2812_LED_INVALID;
// Write color to frame buffer
uint32_t bit;
for (bit = 0; bit < 8; bit++) {
ws2812_frame_buffer[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
ws2812_frame_buffer[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
}
// Success
return WS2812_SUCCESS;
} }
/** @} addtogroup WS2812 */ void testPatternFB(uint8_t *fb){
int i;
Color tmpC = {rand()%256, rand()%256, rand()%256};
for (i=0;i<sLeds;i++){
setColorRGB(tmpC,fb+24*i, sMask);
}
}
void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) { void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) {
uint8_t i = 0; // uint8_t i = 0;
while (i < number_of_leds) { // while (i < number_of_leds) {
ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b); // ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b);
i++; // i++;
} // }
} }

@ -1,102 +1,31 @@
/** /*
* @file ws2812.h * LEDDriver.h
* @author Austin Glaser <austin.glaser@gmail.com>
* @brief Interface to WS2812 LED driver
* *
* Copyright (C) 2016 Austin Glaser * Created on: Aug 26, 2013
* * Author: Omri Iluz
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*
* @todo Put in names and descriptions of variables which need to be defined to use this file
*/ */
#ifndef WS2812_H_ #ifndef WS2812_H_
#define WS2812_H_ #define WS2812_H_
/** #include "hal.h"
* @defgroup WS2812 WS2812 Driver
* @{
*
* @brief DMA-based WS2812 LED driver
*
* A driver for WS2812 LEDs
*/
/* --- PUBLIC DEPENDENCIES -------------------------------------------------- */
// Standard
#include <stdint.h>
#include "rgblight_types.h" #include "rgblight_types.h"
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */ #define sign(x) (( x > 0 ) - ( x < 0 ))
/**
* @brief Return codes from ws2812 interface functions
*/
typedef enum {
WS2812_SUCCESS = 0x00, /**< Operation completeed successfully */
WS2812_LED_INVALID, /**< Attempted to index an invalid LED (@ref WS2812_N_LEDS) */
MAX_WS2812_ERR, /**< Total number of possible error codes */
WS2812_ERR_INVALID /**< Invalid error value */
} ws2812_err_t;
/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */
/**
* @brief Initialize the driver
*
* After this function is called, all necessary background tasks will be started.
* The frame is initially dark.
*/
void ws2812_init(void);
/** typedef struct Color Color;
* @brief Write the value of a single LED in the chain struct Color {
* uint8_t R;
* The color value is written to a frame buffer, and will not uint8_t G;
* be updated until the next frame is written. Frames are written uint8_t B;
* at the maximum possible speed -- the longest latency between a };
* call to this function and the value being displayed is
* 1.25uS*(24*@ref WS2812_LED_N + 50)
*
* @param[in] led_number: The index of the LED to be written. Must be strictly less than
* @ref WS2812_N_LEDS
* @param[in] r: The red level of the LED
* @param[in] g: The green level of the LED
* @param[in] b: The blue level of the LED
*
* @retval WS2812_SUCCESS: The write was successful
* @retval WS2812_LED_INVALID: The write was to an invalid LED index
*/
ws2812_err_t ws2812_write_led(uint32_t led_number, uint8_t r, uint8_t g, uint8_t b);
/** @} defgroup WS2812 */ void ledDriverInit(int leds, stm32_gpio_t *port, uint32_t mask, uint8_t **o_fb);
void setColorRGB(Color c, uint8_t *buf, uint32_t mask);
void testPatternFB(uint8_t *fb);
void ledDriverWaitCycle(void);
void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds);
void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds);
/** #endif /* LEDDRIVER_H_ */
* @brief Concatenates two symbols s1 and s2 exactly, without expanding either
*
* @param[in] s1: The first symbol to concatenate
* @param[in] s2: The second symbol to concatenate
*
* @return A single symbol containing s1 and s2 concatenated without expansion
*/
#define CONCAT_SYMBOLS(s1, s2) s1##s2
/**
* @brief Concatenate the symbols s1 and s2, expanding both of them
*
* This is important because simply applying s1##s2 doesn't expand them if they're
* preprocessor tokens themselves
*
* @param[in] s1: The first symbol to concatenate
* @param[in] s2: The second symbol to concatenate
*
* @return A single symbol containing s1 expanded followed by s2 expanded
*/
#define CONCAT_EXPANDED_SYMBOLS(s1, s2) CONCAT_SYMBOLS(s1, s2)
#endif /* WS2812_H_ */

@ -277,7 +277,7 @@
PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) PIN_OTYPE_PUSHPULL(GPIOA_PIN15))
#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \ #define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \
PIN_OSPEED_VERYLOW(GPIOA_PIN1) | \ PIN_OSPEED_HIGH(GPIOA_PIN1) | \
PIN_OSPEED_VERYLOW(GPIOA_PIN2) | \ PIN_OSPEED_VERYLOW(GPIOA_PIN2) | \
PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \ PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \
PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \ PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \
@ -293,7 +293,7 @@
PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
PIN_OSPEED_VERYLOW(GPIOA_PIN15)) PIN_OSPEED_VERYLOW(GPIOA_PIN15))
#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_PIN0) | \ #define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_PIN0) | \
PIN_PUPDR_PULLUP(GPIOA_PIN1) | \ PIN_PUPDR_FLOATING(GPIOA_PIN1) | \
PIN_PUPDR_PULLUP(GPIOA_PIN2) | \ PIN_PUPDR_PULLUP(GPIOA_PIN2) | \
PIN_PUPDR_PULLUP(GPIOA_PIN3) | \ PIN_PUPDR_PULLUP(GPIOA_PIN3) | \
PIN_PUPDR_PULLUP(GPIOA_PIN4) | \ PIN_PUPDR_PULLUP(GPIOA_PIN4) | \

@ -184,6 +184,7 @@
#define STM32_PWM_USE_ADVANCED FALSE #define STM32_PWM_USE_ADVANCED FALSE
#define STM32_PWM_USE_TIM1 FALSE #define STM32_PWM_USE_TIM1 FALSE
#define STM32_PWM_USE_TIM2 TRUE #define STM32_PWM_USE_TIM2 TRUE
#define STM32_PWM_USE_TIM3 TRUE
#define STM32_PWM_USE_TIM4 FALSE #define STM32_PWM_USE_TIM4 FALSE
#define STM32_PWM_USE_TIM8 FALSE #define STM32_PWM_USE_TIM8 FALSE
#define STM32_PWM_TIM1_IRQ_PRIORITY 7 #define STM32_PWM_TIM1_IRQ_PRIORITY 7
@ -224,7 +225,7 @@
* ST driver system settings. * ST driver system settings.
*/ */
#define STM32_ST_IRQ_PRIORITY 8 #define STM32_ST_IRQ_PRIORITY 8
#define STM32_ST_USE_TIMER 3 #define STM32_ST_USE_TIMER 4
/* /*
* UART driver system settings. * UART driver system settings.

@ -16,21 +16,20 @@
#include "rev6.h" #include "rev6.h"
#include "rgblight.h" #include "rgblight.h"
uint8_t *o_fb;
void matrix_init_kb(void) { void matrix_init_kb(void) {
// rgblight_enable(); // rgblight_enable();
// rgblight_mode(1); // rgblight_mode(1);
// rgblight_setrgb(0xFF, 0xFF, 0xFF); // rgblight_setrgb(0xFF, 0xFF, 0xFF);
ws2812_init();
ledDriverInit(2, GPIOA, 0b00000010, &o_fb);
testPatternFB(o_fb);
matrix_init_user(); matrix_init_user();
} }
void matrix_scan_kb(void) { void matrix_scan_kb(void) {
matrix_scan_user(); matrix_scan_user();
testPatternFB(o_fb);
int s = 0;
for (int n = 0; n < WS2812_LED_N; n++) {
int s0 = s + 10*n;
ws2812_write_led(n, s0%255, (s0+85)%255, (s0+170)%255);
}
s += 10;
} }

Loading…
Cancel
Save