mirror of
https://github.com/tdaede/td-io.git
synced 2025-02-22 05:19:32 +01:00
ws2812
This commit is contained in:
parent
8878a77cfd
commit
57ccfa7505
@ -13,10 +13,13 @@ pico_sdk_init()
|
||||
|
||||
add_executable(td-io
|
||||
td-io.c
|
||||
ws2812.c
|
||||
)
|
||||
|
||||
pico_generate_pio_header(td-io ${CMAKE_CURRENT_LIST_DIR}/ws2812.pio OUTPUT_DIR ${CMAKE_CURRENT_LIST_DIR}/generated)
|
||||
|
||||
# Pull in our pico_stdlib which aggregates commonly used features
|
||||
target_link_libraries(td-io pico_stdlib hardware_adc)
|
||||
target_link_libraries(td-io pico_stdlib hardware_adc hardware_pio)
|
||||
|
||||
# enable usb output, disable uart output
|
||||
pico_enable_stdio_usb(td-io 1)
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/adc.h"
|
||||
#include <string.h>
|
||||
#include "ws2812.h"
|
||||
|
||||
const uint PIN_JVS_RE = 2;
|
||||
const uint PIN_JVS_DE = 3;
|
||||
@ -254,6 +255,11 @@ int main() {
|
||||
|
||||
update_termination();
|
||||
|
||||
init_ws2812(27);
|
||||
|
||||
int ws2812_counter = 0;
|
||||
uint32_t switches;
|
||||
|
||||
while (true) {
|
||||
uint8_t sync = uart_getc(uart0);
|
||||
if (sync == 0xe0) {
|
||||
@ -363,7 +369,7 @@ int main() {
|
||||
}
|
||||
msg_send[o] = JVS_REPORT_GOOD;
|
||||
o++;
|
||||
uint32_t switches = read_switches();
|
||||
switches = read_switches();
|
||||
process_coin(switches);
|
||||
msg_send[o] = ((switches >> SR_TEST) & 1) << 7
|
||||
| ((switches >> SR_TILT) & 1) << 7;
|
||||
@ -509,6 +515,14 @@ int main() {
|
||||
update_termination(); // convenient time to read adc
|
||||
//printf("Saw non-sync code %02x\n", sync);
|
||||
}
|
||||
if ((switches >> SR_P1_1) & 1) {
|
||||
pattern_snakes_green(60, ws2812_counter);
|
||||
} else if ((switches >> SR_P1_2) & 1) {
|
||||
pattern_sparkle_yellow(60, ws2812_counter);
|
||||
} else {
|
||||
pattern_snakes_green_fast(60, ws2812_counter);
|
||||
}
|
||||
ws2812_counter += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
155
firmware/ws2812.c
Normal file
155
firmware/ws2812.c
Normal file
@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/pio.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "ws2812.pio.h"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void pattern_snakes(uint len, uint t) {
|
||||
for (uint i = 0; i < len; ++i) {
|
||||
uint x = (i + (t >> 1)) % 64;
|
||||
if (x < 10)
|
||||
put_pixel(urgb_u32(0xff, 0, 0));
|
||||
else if (x >= 15 && x < 25)
|
||||
put_pixel(urgb_u32(0, 0xff, 0));
|
||||
else if (x >= 30 && x < 40)
|
||||
put_pixel(urgb_u32(0, 0, 0xff));
|
||||
else
|
||||
put_pixel(0);
|
||||
}
|
||||
}
|
||||
|
||||
void pattern_snakes_green(uint len, uint t) {
|
||||
for (uint i = 0; i < len; ++i) {
|
||||
uint x = (i + (t >> 1)) % 64;
|
||||
if (x < 10)
|
||||
put_pixel(urgb_u32(0, 0x10, 0));
|
||||
else if (x >= 15 && x < 25)
|
||||
put_pixel(urgb_u32(0, 0x30, 0));
|
||||
else if (x >= 30 && x < 40)
|
||||
put_pixel(urgb_u32(0, 0xff, 0));
|
||||
else
|
||||
put_pixel(0);
|
||||
}
|
||||
}
|
||||
|
||||
void pattern_snakes_green_fast(uint len, uint t) {
|
||||
for (uint i = 0; i < len; ++i) {
|
||||
uint x = (i + (t >> 0)) % 64;
|
||||
if (x < 10)
|
||||
put_pixel(urgb_u32(0, 0x10, 0));
|
||||
else if (x >= 15 && x < 25)
|
||||
put_pixel(urgb_u32(0, 0x30, 0));
|
||||
else if (x >= 30 && x < 40)
|
||||
put_pixel(urgb_u32(0, 0xff, 0));
|
||||
else
|
||||
put_pixel(0);
|
||||
}
|
||||
}
|
||||
|
||||
void pattern_random(uint len, uint t) {
|
||||
if (t % 8)
|
||||
return;
|
||||
for (int i = 0; i < len; ++i)
|
||||
put_pixel(rand());
|
||||
}
|
||||
|
||||
void pattern_sparkle(uint len, uint t) {
|
||||
if (t % 4)
|
||||
return;
|
||||
for (int i = 0; i < len; ++i)
|
||||
put_pixel(rand() % 8 ? 0 : 0xffffffff);
|
||||
}
|
||||
|
||||
void pattern_sparkle_green(uint len, uint t) {
|
||||
if (t % 8)
|
||||
return;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
uint8_t a = rand() % 16 ? 0 : 0xff;
|
||||
put_pixel(urgb_u32(0, 0xa, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void pattern_sparkle_yellow(uint len, uint t) {
|
||||
if (t % 4)
|
||||
return;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
uint8_t a = rand() % 8 ? 0 : 0xff;
|
||||
put_pixel(urgb_u32(a, a, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void pattern_greys(uint len, uint t) {
|
||||
int max = 100; // let's not draw too much current!
|
||||
t %= max;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
put_pixel(t * 0x10101);
|
||||
if (++t >= max) t = 0;
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*pattern)(uint len, uint t);
|
||||
const struct {
|
||||
pattern pat;
|
||||
const char *name;
|
||||
} pattern_table[] = {
|
||||
{pattern_snakes, "Snakes!"},
|
||||
{pattern_random, "Random data"},
|
||||
{pattern_sparkle, "Sparkles"},
|
||||
{pattern_greys, "Greys"},
|
||||
};
|
||||
|
||||
const int PIN_TX = 27;
|
||||
|
||||
void init_ws2812(int pin) {
|
||||
// todo get free sm
|
||||
PIO pio = pio0;
|
||||
int sm = 0;
|
||||
uint offset = pio_add_program(pio, &ws2812_program);
|
||||
|
||||
ws2812_program_init(pio, sm, offset, pin, 800000, false);
|
||||
}
|
||||
|
||||
int run_ws2812() {
|
||||
//set_sys_clock_48();
|
||||
stdio_init_all();
|
||||
puts("WS2812 Smoke Test");
|
||||
|
||||
// todo get free sm
|
||||
PIO pio = pio0;
|
||||
int sm = 0;
|
||||
uint offset = pio_add_program(pio, &ws2812_program);
|
||||
|
||||
ws2812_program_init(pio, sm, offset, PIN_TX, 80000, false);
|
||||
|
||||
int t = 0;
|
||||
while (1) {
|
||||
int pat = rand() % count_of(pattern_table);
|
||||
int dir = (rand() >> 30) & 1 ? 1 : -1;
|
||||
puts(pattern_table[pat].name);
|
||||
puts(dir == 1 ? "(forward)" : "(backward)");
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
pattern_table[pat].pat(150, t);
|
||||
sleep_ms(10);
|
||||
t += dir;
|
||||
}
|
||||
}
|
||||
}
|
8
firmware/ws2812.h
Normal file
8
firmware/ws2812.h
Normal file
@ -0,0 +1,8 @@
|
||||
void run_ws2812(void);
|
||||
void init_ws2812(int);
|
||||
|
||||
void pattern_sparkle_green(uint len, uint t);
|
||||
void pattern_sparkle_yellow(uint len, uint t);
|
||||
void pattern_snakes_green(uint len, uint t);
|
||||
void pattern_greys(uint len, uint t);
|
||||
void pattern_snakes_green_fast(uint len, uint t);
|
85
firmware/ws2812.pio
Normal file
85
firmware/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…
x
Reference in New Issue
Block a user