aboutsummaryrefslogtreecommitdiff
path: root/include/ws2812b.h
blob: e814b65a189e695c3c9f803cd61036a7a0099a80 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#pragma once

#include <stdint.h>
#include <stdlib.h>

#define WIRE_BYTES_PER_COLOR 9
#define PADDING_BYTES 1
#define TOTAL_BYTES_PER_LED (PADDING_BYTES + WIRE_BYTES_PER_COLOR)

enum ws2812b_byte_order {
  BYTE_ORDER_RGB = 0,
  BYTE_ORDER_GBR = 1,
};

struct ws2812b_buf {
  uint8_t* buf;       /* Size of the buffer. */
  size_t total_alloc; /* total number of bytes allocated to the buffer. */
  size_t cur;         /* Current output cursor in the buffer */

  /* The byte order this driver should use. WS2811's use BGR, WS2812b's use GBR.
   */
  enum ws2812b_byte_order byte_order;

  /* pointer to the dma_now register. needed to synchronize with the DMA. */
  volatile uint16_t* dma_now_reg;

  /* pointer to the dma_end register. */
  volatile uint16_t* dma_end_reg;
};

struct rgb_compiled {
  union {
    struct __attribute__((packed)) {
      uint32_t first_bits;
      uint32_t second_bits;
      uint8_t last_bits;
    };
    uint8_t buf[9];
  };
};

typedef struct {
  union {
    struct __attribute__((packed)) {
      uint8_t r;
      uint8_t g;
      uint8_t b;
    };
    uint32_t color;
  };
} rgb_t;

int write_rgb(struct ws2812b_buf* out, rgb_t color);

void start_dma(struct ws2812b_buf* buf);

void make_wsb2812b(struct ws2812b_buf* out, void* buf, size_t n_alloc);

void compile_color(
    rgb_t color, struct rgb_compiled* out, enum ws2812b_byte_order byte_order);

// ch must have at least 73 characters free.
void compiled_color_dbg_str(struct rgb_compiled* c, char* out);