mirror of
https://github.com/whowechina/popn_pico.git
synced 2024-11-24 06:50:18 +01:00
RGB lights working.
This commit is contained in:
parent
07427cff5b
commit
5a7828c496
@ -1,9 +1,10 @@
|
||||
add_executable(${PROJECT_NAME} main.c buttons.c usb_descriptors.c)
|
||||
add_executable(${PROJECT_NAME} main.c buttons.c rgb.c usb_descriptors.c)
|
||||
|
||||
pico_generate_pio_header(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/ws2812.pio)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Werror -Wfatal-errors -O3)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
pico_multicore pico_stdlib tinyusb_device tinyusb_board)
|
||||
pico_multicore pico_stdlib hardware_pio tinyusb_device tinyusb_board)
|
||||
|
||||
# Make a UF2 binary
|
||||
pico_add_extra_outputs(${PROJECT_NAME})
|
||||
|
@ -9,8 +9,9 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/timer.h>
|
||||
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/timer.h"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
#include "buttons.h"
|
||||
#include "rgb.h"
|
||||
|
||||
uint64_t hid_lights_timeout = 0;
|
||||
|
||||
@ -43,11 +44,13 @@ void main_loop()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void init()
|
||||
{
|
||||
board_init();
|
||||
tusb_init();
|
||||
button_init();
|
||||
rgb_init();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
@ -83,12 +86,15 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id,
|
||||
{
|
||||
if ((report_id == REPORT_ID_LIGHTS) &&
|
||||
(report_type == HID_REPORT_TYPE_OUTPUT)) {
|
||||
if (bufsize < button_num()) {
|
||||
if (bufsize < button_num() + 3) { /* including logo rgb */
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < button_num(); i++) {
|
||||
button_lights[i] = (buffer[i] > 0);
|
||||
}
|
||||
uint8_t const *rgb = buffer + button_num();
|
||||
rgb_update_logo(rgb[0], rgb[1], rgb[2]);
|
||||
|
||||
hid_lights_timeout = time_us_64() + 1000000; /* 1 second */
|
||||
}
|
||||
}
|
||||
|
52
FIRMWARE/src/rgb.c
Normal file
52
FIRMWARE/src/rgb.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Pico Popn Controller Buttons
|
||||
* WHowe <whowe@gmail.com>
|
||||
*
|
||||
* A button consists of a switch and an LED
|
||||
*/
|
||||
|
||||
#include "buttons.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "pico/multicore.h"
|
||||
#include "hardware/pio.h"
|
||||
|
||||
#include "ws2812.pio.h"
|
||||
|
||||
#define WS2812_PIN 28
|
||||
|
||||
static inline void put_pixel(uint32_t pixel_grb)
|
||||
{
|
||||
pio_sm_put_blocking(pio0, 0, pixel_grb << 8u);
|
||||
}
|
||||
|
||||
static inline uint32_t urgb_u32(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
return ((uint32_t)r << 8) | ((uint32_t)g << 16) | (uint32_t)b;
|
||||
}
|
||||
|
||||
static uint32_t logo_color = 0;
|
||||
|
||||
void rgb_update_logo(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
logo_color = urgb_u32(r, g, b);
|
||||
}
|
||||
|
||||
void rgb_entry()
|
||||
{
|
||||
while (1) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
put_pixel(logo_color);
|
||||
}
|
||||
sleep_ms(10);
|
||||
}
|
||||
}
|
||||
|
||||
void rgb_init()
|
||||
{
|
||||
uint offset = pio_add_program(pio0, &ws2812_program);
|
||||
ws2812_program_init(pio0, 0, offset, WS2812_PIN, 800000, false);
|
||||
multicore_launch_core1(rgb_entry);
|
||||
}
|
14
FIRMWARE/src/rgb.h
Normal file
14
FIRMWARE/src/rgb.h
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Pico Popn Controller Buttons
|
||||
* WHowe <whowechina@github>
|
||||
*/
|
||||
|
||||
#ifndef RGB_H
|
||||
#define RGB_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void rgb_init();
|
||||
void rgb_update_logo(uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
#endif
|
@ -41,7 +41,7 @@ enum {
|
||||
#define GAMECON_REPORT_DESC_LIGHTS(...) \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), HID_USAGE(0x00), \
|
||||
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
|
||||
__VA_ARGS__ HID_REPORT_COUNT(9 + 3), /*LED NUM + RGB */ \
|
||||
__VA_ARGS__ HID_REPORT_COUNT(11 + 3), /*LED NUM + RGB */ \
|
||||
HID_REPORT_SIZE(8), HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX_N(0x00ff, 2), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_ORDINAL), HID_STRING_MINIMUM(4), \
|
||||
HID_STRING_MAXIMUM(16), HID_USAGE_MIN(1), HID_USAGE_MAX(16), \
|
||||
|
85
FIRMWARE/src/ws2812.pio
Normal file
85
FIRMWARE/src/ws2812.pio
Normal file
@ -0,0 +1,85 @@
|
||||
;
|
||||
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
;
|
||||
; SPDX-License-Identifier: BSD-3-Clause
|
||||
;
|
||||
|
||||
.program ws2812
|
||||
.side_set 1
|
||||
|
||||
.define public T1 2
|
||||
.define public T2 5
|
||||
.define public T3 3
|
||||
|
||||
.lang_opt python sideset_init = pico.PIO.OUT_HIGH
|
||||
.lang_opt python out_init = pico.PIO.OUT_HIGH
|
||||
.lang_opt python out_shiftdir = 1
|
||||
|
||||
.wrap_target
|
||||
bitloop:
|
||||
out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls
|
||||
jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
|
||||
do_one:
|
||||
jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse
|
||||
do_zero:
|
||||
nop side 0 [T2 - 1] ; Or drive low, for a short pulse
|
||||
.wrap
|
||||
|
||||
% c-sdk {
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) {
|
||||
|
||||
pio_gpio_init(pio, pin);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||
|
||||
pio_sm_config c = ws2812_program_get_default_config(offset);
|
||||
sm_config_set_sideset_pins(&c, pin);
|
||||
sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
|
||||
int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3;
|
||||
float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
|
||||
sm_config_set_clkdiv(&c, div);
|
||||
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
%}
|
||||
|
||||
.program ws2812_parallel
|
||||
|
||||
.define public T1 2
|
||||
.define public T2 5
|
||||
.define public T3 3
|
||||
|
||||
.wrap_target
|
||||
out x, 32
|
||||
mov pins, !null [T1-1]
|
||||
mov pins, x [T2-1]
|
||||
mov pins, null [T3-2]
|
||||
.wrap
|
||||
|
||||
% c-sdk {
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
static inline void ws2812_parallel_program_init(PIO pio, uint sm, uint offset, uint pin_base, uint pin_count, float freq) {
|
||||
for(uint i=pin_base; i<pin_base+pin_count; i++) {
|
||||
pio_gpio_init(pio, i);
|
||||
}
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin_base, pin_count, true);
|
||||
|
||||
pio_sm_config c = ws2812_parallel_program_get_default_config(offset);
|
||||
sm_config_set_out_shift(&c, true, true, 32);
|
||||
sm_config_set_out_pins(&c, pin_base, pin_count);
|
||||
sm_config_set_set_pins(&c, pin_base, pin_count);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
|
||||
int cycles_per_bit = ws2812_parallel_T1 + ws2812_parallel_T2 + ws2812_parallel_T3;
|
||||
float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
|
||||
sm_config_set_clkdiv(&c, div);
|
||||
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
%}
|
Loading…
Reference in New Issue
Block a user