ws2812.pio 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. ;
  2. ; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
  3. ;
  4. ; SPDX-License-Identifier: BSD-3-Clause
  5. ;
  6. .program ws2812
  7. .side_set 1
  8. .define public T1 2
  9. .define public T2 5
  10. .define public T3 3
  11. .lang_opt python sideset_init = pico.PIO.OUT_HIGH
  12. .lang_opt python out_init = pico.PIO.OUT_HIGH
  13. .lang_opt python out_shiftdir = 1
  14. .wrap_target
  15. bitloop:
  16. out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls
  17. jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
  18. do_one:
  19. jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse
  20. do_zero:
  21. nop side 0 [T2 - 1] ; Or drive low, for a short pulse
  22. .wrap
  23. % c-sdk {
  24. #include "hardware/clocks.h"
  25. static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) {
  26. pio_gpio_init(pio, pin);
  27. pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
  28. pio_sm_config c = ws2812_program_get_default_config(offset);
  29. sm_config_set_sideset_pins(&c, pin);
  30. sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24);
  31. sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
  32. int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3;
  33. float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
  34. sm_config_set_clkdiv(&c, div);
  35. pio_sm_init(pio, sm, offset, &c);
  36. pio_sm_set_enabled(pio, sm, true);
  37. }
  38. %}
  39. .program ws2812_parallel
  40. .define public T1 2
  41. .define public T2 5
  42. .define public T3 3
  43. .wrap_target
  44. out x, 32
  45. mov pins, !null [T1-1]
  46. mov pins, x [T2-1]
  47. mov pins, null [T3-2]
  48. .wrap
  49. % c-sdk {
  50. #include "hardware/clocks.h"
  51. static inline void ws2812_parallel_program_init(PIO pio, uint sm, uint offset, uint pin_base, uint pin_count, float freq) {
  52. for(uint i=pin_base; i<pin_base+pin_count; i++) {
  53. pio_gpio_init(pio, i);
  54. }
  55. pio_sm_set_consecutive_pindirs(pio, sm, pin_base, pin_count, true);
  56. pio_sm_config c = ws2812_parallel_program_get_default_config(offset);
  57. sm_config_set_out_shift(&c, true, true, 32);
  58. sm_config_set_out_pins(&c, pin_base, pin_count);
  59. sm_config_set_set_pins(&c, pin_base, pin_count);
  60. sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
  61. int cycles_per_bit = ws2812_parallel_T1 + ws2812_parallel_T2 + ws2812_parallel_T3;
  62. float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
  63. sm_config_set_clkdiv(&c, div);
  64. pio_sm_init(pio, sm, offset, &c);
  65. pio_sm_set_enabled(pio, sm, true);
  66. }
  67. %}