2021-07-16 17:01:55 +01:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
This code is significantly modified from the PIO apa102 example
|
|
|
|
found here: https://github.com/raspberrypi/pico-examples/tree/master/pio/ws2812
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
#include "ws2812.pio.h"
|
|
|
|
|
|
|
|
#include "pico/stdlib.h"
|
|
|
|
#include "hardware/pio.h"
|
|
|
|
#include "hardware/dma.h"
|
|
|
|
#include "hardware/irq.h"
|
|
|
|
#include "hardware/clocks.h"
|
|
|
|
#include "hardware/timer.h"
|
|
|
|
|
|
|
|
namespace plasma {
|
|
|
|
|
|
|
|
class WS2812 {
|
|
|
|
public:
|
|
|
|
static const uint SERIAL_FREQ_400KHZ = 400000;
|
|
|
|
static const uint SERIAL_FREQ_800KHZ = 800000;
|
2021-08-19 15:36:25 +01:00
|
|
|
static const uint DEFAULT_SERIAL_FREQ = SERIAL_FREQ_800KHZ;
|
2021-08-02 12:33:20 +01:00
|
|
|
enum class COLOR_ORDER {
|
|
|
|
RGB,
|
|
|
|
RBG,
|
|
|
|
GRB,
|
|
|
|
GBR,
|
|
|
|
BRG,
|
|
|
|
BGR
|
|
|
|
};
|
2021-07-16 17:01:55 +01:00
|
|
|
#pragma pack(push, 1)
|
|
|
|
union alignas(4) RGB {
|
|
|
|
struct {
|
|
|
|
uint8_t r;
|
|
|
|
uint8_t g;
|
|
|
|
uint8_t b;
|
|
|
|
uint8_t w = 0b00000000;
|
|
|
|
} ;
|
|
|
|
uint32_t srgb;
|
|
|
|
void operator=(uint32_t v) {
|
|
|
|
srgb = v;
|
|
|
|
};
|
2021-08-02 12:33:20 +01:00
|
|
|
void rgb(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0) {
|
2021-07-16 17:01:55 +01:00
|
|
|
this->r = r;
|
|
|
|
this->g = g;
|
|
|
|
this->b = b;
|
2021-08-02 12:33:20 +01:00
|
|
|
this->w = w;
|
|
|
|
};
|
|
|
|
RGB() : r(0), g(0), b(0), w(0) {};
|
2021-07-16 17:01:55 +01:00
|
|
|
};
|
|
|
|
#pragma pack(pop)
|
|
|
|
RGB *buffer;
|
|
|
|
uint32_t num_leds;
|
2021-08-02 12:33:20 +01:00
|
|
|
COLOR_ORDER color_order;
|
2021-07-16 17:01:55 +01:00
|
|
|
|
2021-08-23 17:18:34 +01:00
|
|
|
WS2812(uint num_leds, PIO pio, uint sm, uint pin, uint freq=DEFAULT_SERIAL_FREQ, bool rgbw=false, COLOR_ORDER color_order=COLOR_ORDER::GRB, RGB* buffer=nullptr);
|
2021-07-21 14:51:37 +01:00
|
|
|
~WS2812() {
|
|
|
|
stop();
|
|
|
|
clear();
|
|
|
|
update(true);
|
|
|
|
dma_channel_unclaim(dma_channel);
|
2021-08-25 16:02:06 +01:00
|
|
|
pio_sm_set_enabled(pio, sm, false);
|
|
|
|
pio_remove_program(pio, &ws2812_program, pio_program_offset);
|
|
|
|
#ifndef MICROPY_BUILD_TYPE
|
|
|
|
// pio_sm_unclaim seems to hardfault in MicroPython
|
2021-07-21 14:51:37 +01:00
|
|
|
pio_sm_unclaim(pio, sm);
|
2021-08-25 16:02:06 +01:00
|
|
|
#endif
|
2021-08-25 21:57:00 +01:00
|
|
|
if(managed_buffer) {
|
|
|
|
// Only delete buffers we have allocated ourselves.
|
|
|
|
delete[] buffer;
|
|
|
|
}
|
2021-07-21 14:51:37 +01:00
|
|
|
}
|
2021-07-16 17:01:55 +01:00
|
|
|
bool start(uint fps=60);
|
|
|
|
bool stop();
|
|
|
|
void update(bool blocking=false);
|
2021-07-21 14:51:37 +01:00
|
|
|
void clear();
|
2021-12-03 10:50:06 +00:00
|
|
|
void set_hsv(uint32_t index, float h, float s, float v, uint8_t w=0);
|
2021-09-13 17:35:25 +01:00
|
|
|
void set_rgb(uint32_t index, uint8_t r, uint8_t g, uint8_t b, uint8_t w=0, bool gamma=true);
|
2021-07-16 17:01:55 +01:00
|
|
|
void set_brightness(uint8_t b);
|
|
|
|
RGB get(uint32_t index) {return buffer[index];};
|
|
|
|
|
|
|
|
static bool dma_timer_callback(struct repeating_timer *t);
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint32_t fps;
|
|
|
|
PIO pio;
|
|
|
|
uint sm;
|
2021-08-25 16:02:06 +01:00
|
|
|
uint pio_program_offset;
|
2021-07-16 17:01:55 +01:00
|
|
|
int dma_channel;
|
|
|
|
struct repeating_timer timer;
|
2021-08-25 21:57:00 +01:00
|
|
|
bool managed_buffer = false;
|
2021-07-16 17:01:55 +01:00
|
|
|
};
|
|
|
|
}
|