add: add RGBW LED strip control
This commit is contained in:
parent
beb6d33f85
commit
0250d81862
197
application.c
197
application.c
@ -102,6 +102,18 @@ static volatile uint32_t dial_steps = 0; /**< set to drv8825_steps when dial is
|
||||
static uint8_t rgbmatrix_data[RGBMATRIX_HEIGHT / 2][RGBMATRIX_WIDTH * 2]; /**< data to be sent to RGB matrix (one byte includes upper and lower half values, each byte has 2 clock edges) */
|
||||
#define RGBMATRIX_TIMER 3 /**< timer to update lines */
|
||||
|
||||
// RGBW LED strips
|
||||
#define STRIP_TIMER 4 /**< timer used for the PWM */
|
||||
#define STRIP_R_PIN PB9 /**< pin used to drive gate for red channel */
|
||||
#define STRIP_R_CH 4 /**< channel used for the red channel */
|
||||
#define STRIP_G_PIN PB8 /**< pin used to drive gate for green channel */
|
||||
#define STRIP_G_CH 3 /**< channel used for the green channel */
|
||||
#define STRIP_B_PIN PB7 /**< pin used to drive gate for blue channel */
|
||||
#define STRIP_B_CH 2 /**< channel used for the blue channel */
|
||||
#define STRIP_W_PIN PB6 /**< pin used to drive gate for white channel */
|
||||
#define STRIP_W_CH 1 /**< channel used for the white channel */
|
||||
#define STRIP_AF GPIO_AF2 /**< alternate function for pin to be used as timer channel */
|
||||
|
||||
/** set motor speed and direction
|
||||
* @param[in] speed speed (in Hz) and direction (sign)
|
||||
*/
|
||||
@ -552,6 +564,88 @@ static void command_matrix(void* argument)
|
||||
rgbmatrix_set(2, 3, false, false, true);
|
||||
}
|
||||
|
||||
/** set intensity of LED strip
|
||||
* @param[in] red red intensity (0-0xffff), -1 to leave
|
||||
* @param[in] green green intensity (0-0xffff), -1 to leave
|
||||
* @param[in] blue blue intensity (0-0xffff), -1 to leave
|
||||
* @param[in] white white intensity (0-0xffff), -1 to leave
|
||||
*/
|
||||
static void strip_rgbw(int32_t red, int32_t green, int32_t blue, int32_t white)
|
||||
{
|
||||
if (red >= 0 && red <= 0xffff) {
|
||||
timer_set_oc_value(TIM(STRIP_TIMER), TIM_OC(STRIP_R_CH), red);
|
||||
}
|
||||
if (green >= 0 && green <= 0xffff) {
|
||||
timer_set_oc_value(TIM(STRIP_TIMER), TIM_OC(STRIP_G_CH), green);
|
||||
}
|
||||
if (blue >= 0 && blue <= 0xffff) {
|
||||
timer_set_oc_value(TIM(STRIP_TIMER), TIM_OC(STRIP_B_CH), blue);
|
||||
}
|
||||
if (white >= 0 && white <= 0xffff) {
|
||||
timer_set_oc_value(TIM(STRIP_TIMER), TIM_OC(STRIP_W_CH), white);
|
||||
}
|
||||
}
|
||||
|
||||
static void command_strip_red(void* argument)
|
||||
{
|
||||
if (!argument) {
|
||||
printf("argument required\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t set = *(uint32_t*)argument; // get provide value
|
||||
if (set > 100) {
|
||||
set = 100; // enforce maximum
|
||||
}
|
||||
strip_rgbw(0xffff * set / 100, -1, -1, -1); // set light intensity
|
||||
printf("red channel set to %u%%\n", set);
|
||||
}
|
||||
|
||||
static void command_strip_green(void* argument)
|
||||
{
|
||||
if (!argument) {
|
||||
printf("argument required\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t set = *(uint32_t*)argument; // get provide value
|
||||
if (set > 100) {
|
||||
set = 100; // enforce maximum
|
||||
}
|
||||
strip_rgbw(-1, 0xffff * set / 100, -1, -1); // set light intensity
|
||||
printf("green channel set to %u%%\n", set);
|
||||
}
|
||||
|
||||
static void command_strip_blue(void* argument)
|
||||
{
|
||||
if (!argument) {
|
||||
printf("argument required\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t set = *(uint32_t*)argument; // get provide value
|
||||
if (set > 100) {
|
||||
set = 100; // enforce maximum
|
||||
}
|
||||
strip_rgbw(-1, -1, 0xffff * set / 100, -1); // set light intensity
|
||||
printf("blue channel set to %u%%\n", set);
|
||||
}
|
||||
|
||||
static void command_strip_white(void* argument)
|
||||
{
|
||||
if (!argument) {
|
||||
printf("argument required\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t set = *(uint32_t*)argument; // get provide value
|
||||
if (set > 100) {
|
||||
set = 100; // enforce maximum
|
||||
}
|
||||
strip_rgbw(-1, -1, -1, 0xffff * set / 100); // set light intensity
|
||||
printf("white channel set to %u%%\n", set);
|
||||
}
|
||||
|
||||
/** list of all supported commands */
|
||||
static const struct menu_command_t menu_commands[] = {
|
||||
{
|
||||
@ -634,6 +728,38 @@ static const struct menu_command_t menu_commands[] = {
|
||||
.argument_description = NULL,
|
||||
.command_handler = &command_matrix,
|
||||
},
|
||||
{
|
||||
.shortcut = 'r',
|
||||
.name = "strip_red",
|
||||
.command_description = "set LED strip red intensity",
|
||||
.argument = MENU_ARGUMENT_UNSIGNED,
|
||||
.argument_description = "%",
|
||||
.command_handler = &command_strip_red,
|
||||
},
|
||||
{
|
||||
.shortcut = 'g',
|
||||
.name = "strip_green",
|
||||
.command_description = "set LED strip green intensity",
|
||||
.argument = MENU_ARGUMENT_UNSIGNED,
|
||||
.argument_description = "%",
|
||||
.command_handler = &command_strip_green,
|
||||
},
|
||||
{
|
||||
.shortcut = 'b',
|
||||
.name = "strip_blue",
|
||||
.command_description = "set LED strip blue intensity",
|
||||
.argument = MENU_ARGUMENT_UNSIGNED,
|
||||
.argument_description = "%",
|
||||
.command_handler = &command_strip_blue,
|
||||
},
|
||||
{
|
||||
.shortcut = 'w',
|
||||
.name = "strip_white",
|
||||
.command_description = "set LED strip white intensity",
|
||||
.argument = MENU_ARGUMENT_UNSIGNED,
|
||||
.argument_description = "%",
|
||||
.command_handler = &command_strip_white,
|
||||
},
|
||||
};
|
||||
|
||||
static void command_help(void* argument)
|
||||
@ -865,6 +991,76 @@ void main(void)
|
||||
|
||||
puts_debug("OK\n");
|
||||
|
||||
// setup LED strips
|
||||
puts_debug("setup RGBW LED strips: ");
|
||||
|
||||
// configure pins
|
||||
// red channel
|
||||
rcc_periph_clock_enable(GPIO_RCC(STRIP_R_PIN)); // enable clock for GPIO port peripheral
|
||||
gpio_clear(GPIO_PORT(STRIP_R_PIN), GPIO_PIN(STRIP_R_PIN)); // switch off light
|
||||
gpio_set_output_options(GPIO_PORT(STRIP_R_PIN), GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN(STRIP_R_PIN)); // set slow edge
|
||||
gpio_set_af(GPIO_PORT(STRIP_R_PIN), STRIP_AF, GPIO_PIN(STRIP_R_PIN)); // set alternate function to
|
||||
gpio_mode_setup(GPIO_PORT(STRIP_R_PIN), GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN(STRIP_R_PIN)); // set pin to alternate timer channel
|
||||
// green channel
|
||||
rcc_periph_clock_enable(GPIO_RCC(STRIP_G_PIN)); // enable clock for GPIO port peripheral
|
||||
gpio_clear(GPIO_PORT(STRIP_G_PIN), GPIO_PIN(STRIP_G_PIN)); // switch off light
|
||||
gpio_set_output_options(GPIO_PORT(STRIP_G_PIN), GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN(STRIP_G_PIN)); // set slow edge
|
||||
gpio_set_af(GPIO_PORT(STRIP_G_PIN), STRIP_AF, GPIO_PIN(STRIP_G_PIN)); // set alternate function to
|
||||
gpio_mode_setup(GPIO_PORT(STRIP_G_PIN), GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN(STRIP_G_PIN)); // set pin as output
|
||||
// blue channel
|
||||
rcc_periph_clock_enable(GPIO_RCC(STRIP_B_PIN)); // enable clock for GPIO port peripheral
|
||||
gpio_clear(GPIO_PORT(STRIP_B_PIN), GPIO_PIN(STRIP_B_PIN)); // switch off light
|
||||
gpio_set_output_options(GPIO_PORT(STRIP_B_PIN), GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN(STRIP_B_PIN)); // set slow edge
|
||||
gpio_set_af(GPIO_PORT(STRIP_B_PIN), STRIP_AF, GPIO_PIN(STRIP_B_PIN)); // set alternate function to
|
||||
gpio_mode_setup(GPIO_PORT(STRIP_B_PIN), GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN(STRIP_B_PIN)); // set pin as output
|
||||
// white channel
|
||||
rcc_periph_clock_enable(GPIO_RCC(STRIP_W_PIN)); // enable clock for GPIO port peripheral
|
||||
gpio_clear(GPIO_PORT(STRIP_W_PIN), GPIO_PIN(STRIP_W_PIN)); // switch off light
|
||||
gpio_set_output_options(GPIO_PORT(STRIP_W_PIN), GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN(STRIP_W_PIN)); // set slow edge
|
||||
gpio_set_af(GPIO_PORT(STRIP_W_PIN), STRIP_AF, GPIO_PIN(STRIP_W_PIN)); // set alternate function to
|
||||
gpio_mode_setup(GPIO_PORT(STRIP_W_PIN), GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN(STRIP_W_PIN)); // set pin as output
|
||||
|
||||
// configure timer to generate PWM
|
||||
rcc_periph_clock_enable(RCC_TIM(STRIP_TIMER)); // enable clock for timer peripheral
|
||||
rcc_periph_reset_pulse(RST_TIM(STRIP_TIMER)); // reset timer state
|
||||
timer_disable_counter(TIM(STRIP_TIMER)); // disable timer to configure it
|
||||
timer_set_mode(TIM(STRIP_TIMER), TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); // set timer mode, use undivided timer clock, edge alignment (simple count), and count up
|
||||
timer_set_prescaler(TIM(STRIP_TIMER), 10 - 1); // set presecaler for fast enough for LED PWM and less stress on MOSFET gate ( (84E6/(10 * 2**16))=1281 Hz )
|
||||
// red channel
|
||||
timer_set_oc_mode(TIM(STRIP_TIMER), TIM_OC(STRIP_R_CH), TIM_OCM_PWM1); // set output to PWM mode
|
||||
timer_enable_oc_output(TIM(STRIP_TIMER), TIM_OC(STRIP_R_CH)); // enable PWM output
|
||||
timer_set_oc_value(TIM(STRIP_TIMER), TIM_OC(STRIP_R_CH), 0); // disable light
|
||||
// green channel
|
||||
timer_set_oc_mode(TIM(STRIP_TIMER), TIM_OC(STRIP_G_CH), TIM_OCM_PWM1); // set output to PWM mode
|
||||
timer_enable_oc_output(TIM(STRIP_TIMER), TIM_OC(STRIP_G_CH)); // enable PWM output
|
||||
timer_set_oc_value(TIM(STRIP_TIMER), TIM_OC(STRIP_G_CH), 0); // disable light
|
||||
// blue channel
|
||||
timer_set_oc_mode(TIM(STRIP_TIMER), TIM_OC(STRIP_B_CH), TIM_OCM_PWM1); // set output to PWM mode
|
||||
timer_enable_oc_output(TIM(STRIP_TIMER), TIM_OC(STRIP_B_CH)); // enable PWM output
|
||||
timer_set_oc_value(TIM(STRIP_TIMER), TIM_OC(STRIP_B_CH), 0); // disable light
|
||||
// white channel
|
||||
timer_set_oc_mode(TIM(STRIP_TIMER), TIM_OC(STRIP_W_CH), TIM_OCM_PWM1); // set output to PWM mode
|
||||
timer_enable_oc_output(TIM(STRIP_TIMER), TIM_OC(STRIP_W_CH)); // enable PWM output
|
||||
timer_set_oc_value(TIM(STRIP_TIMER), TIM_OC(STRIP_W_CH), 0); // disable light
|
||||
|
||||
timer_enable_counter(TIM(STRIP_TIMER)); // enable timer to generate PWM
|
||||
/*
|
||||
|
||||
// use comparator to time signal (without using the output), starting at slot start
|
||||
timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC1IF); // clear flag
|
||||
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC1, 1 * (rcc_ahb_frequency / 1000000) - 1); // use compare function to time master pulling low when reading (1 < Tlowr < 15)
|
||||
timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC2IF); // clear flag
|
||||
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC2, 7 * (rcc_ahb_frequency / 1000000) - 1); // use compare function to read or write 0 or 1 (1 < Trw < 15)
|
||||
timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF); // clear flag
|
||||
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC3, 62 * (rcc_ahb_frequency / 1000000) - 1); // use compare function to end time slot (60 < Tslot < 120), this will be followed by a recovery time (end of timer)
|
||||
timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC4IF); // clear flag
|
||||
timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC4, (70 - 10) * (rcc_ahb_frequency / 1000000) - 1); // use compare function to detect slave presence (15 < Tpdh < 60 + 60 < Tpdl < 240), with hand tuning
|
||||
timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_UIF); // clear update (overflow) flag
|
||||
timer_update_on_overflow(TIM(ONEWIRE_MASTER_TIMER)); // only use counter overflow as UEV source (use overflow as start time or timeout)
|
||||
timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_UIE); // enable update interrupt for overflow
|
||||
*/
|
||||
puts_debug("OK\n");
|
||||
|
||||
// setup terminal
|
||||
terminal_prefix = ""; // set default prefix
|
||||
terminal_process = &process_command; // set central function to process commands
|
||||
@ -904,6 +1100,7 @@ void main(void)
|
||||
} else {
|
||||
scroll_pos -= 1;
|
||||
}
|
||||
strip_rgbw(0, 0, 0, (64 - scroll_pos) * 100);
|
||||
}
|
||||
if (second_flag) { // one second passed
|
||||
second_flag = false; // clear flag
|
||||
|
Loading…
Reference in New Issue
Block a user