OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [docs/] [datasheet/] [soc_neoled.adoc] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 60 zero_gravi
<<<
2
:sectnums:
3
==== Smart LED Interface (NEOLED)
4
 
5
[cols="<3,<3,<4"]
6
[frame="topbot",grid="none"]
7
|=======================
8
| Hardware source file(s): | neorv32_neoled.vhd |
9
| Software driver file(s): | neorv32_neoled.c |
10
|                          | neorv32_neoled.h |
11 62 zero_gravi
| Top entity port:         | `neoled_o` | 1-bit serial data output
12
| Configuration generics:  | _IO_NEOLED_EN_      | implement NEOLED when _true_
13
|                          | _IO_NEOLED_TX_FIFO_ | TX FIFO depth (1..32k, has to be a power of two)
14 60 zero_gravi
| CPU interrupts:          | fast IRQ channel 9 | NEOLED interrupt (see <<_processor_interrupts>>)
15
|=======================
16
 
17
**Theory of Operation**
18
 
19
The NEOLED module provides a dedicated interface for "smart RGB LEDs" like the WS2812 or WS2811.
20
These LEDs provide a single interface wire that uses an asynchronous serial protocol for transmitting color
21
data. Basically, data is transferred via LED-internal shift registers, which allows to cascade an unlimited
22
number of smart LEDs. The protocol provides a RESET command to strobe the transmitted data into the
23
LED PWM driver registers after data has shifted throughout all LEDs in a chain.
24
 
25
[NOTE]
26
The NEOLED interface is compatible to the "Adafruit Industries NeoPixel" products, which feature
27
WS2812 (or older WS2811) smart LEDs (see link:https://learn.adafruit.com/adafruit-neopixel-uberguide).
28
 
29 62 zero_gravi
The interface provides a single 1-bit output `neoled_o` to drive an arbitrary number of cascaded LEDs. Since the
30 60 zero_gravi
NEOLED module provides 24-bit and 32-bit operating modes, a mixed setup with RGB LEDs (24-bit color)
31 62 zero_gravi
and RGBW LEDs (32-bit color including a dedicated white LED chip) is possible.
32 60 zero_gravi
 
33 65 zero_gravi
**Theory of Operation - NEOLED Module**
34 62 zero_gravi
 
35 64 zero_gravi
The NEOLED modules provides two accessible interface registers: the control register `CTRL` and the
36
TX data register `DATA`. The NEOLED module is globally enabled via the control register's
37
_NEOLED_CTRL_EN_ bit. Clearing this bit will terminate any current operation, clear the TX buffer, reset the module
38 62 zero_gravi
and set the `neoled_o` output to zero. The precise timing (implementing the **WS2812** protocol) and transmission
39 64 zero_gravi
mode are fully programmable via the `CTRL` register to provide maximum flexibility.
40 62 zero_gravi
 
41
 
42
**RGB / RGBW Configuration**
43
 
44
NeoPixel are available in two "color" version: LEDs with three chips providing RGB color and LEDs with
45
four chips providing RGB color plus a dedicated white LED chip (= RGBW). Since the intensity of every
46
LED chip is defined via an 8-bit value the RGB LEDs require a frame of 24-bit per module and the RGBW
47
LEDs require a frame of 32-bit per module.
48
 
49
The data transfer quantity of the NEOLED module can be configured via the _NEOLED_MODE_EN_ control
50
register bit. If this bit is cleared, the NEOLED interface operates in 24-bit mode and will transmit bits `23:0` of
51 64 zero_gravi
the data written to `DATA` to the LEDs. If _NEOLED_MODE_EN_ is set, the NEOLED interface operates in 32-bit
52
mode and will transmit bits `31:0` of the data written to `DATA` to the LEDs.
53 62 zero_gravi
 
54
The mode bit can be configured before writing each new data word in order to support
55
an arbitrary setup of RGB and RGBW LEDs.
56
 
57
 
58 65 zero_gravi
**Theory of Operation - Protocol**
59 60 zero_gravi
 
60
The interface of the WS2812 LEDs uses an 800kHz carrier signal. Data is transmitted in a serial manner
61 62 zero_gravi
starting with LSB-first. The intensity for each R, G & B (& W) LED chip (= color code) is defined via an 8-bit
62 60 zero_gravi
value. The actual data bits are transferred by modifying the duty cycle of the signal (the timings for the
63
WS2812 are shown below). A RESET command is "send" by pulling the data line LOW for at least 50μs.
64
 
65
.WS2812 bit-level protocol - taken from the "Adafruit NeoPixel Überguide"
66
image::neopixel.png[align=center]
67
 
68
.WS2812 interface timing
69
[cols="<2,<2,<6"]
70
[grid="all"]
71
|=======================
72
| T~total~ (T~carrier~) | 1.25μs +/- 300ns  | period for a single bit
73
| T~0H~                 | 0.4μs +/- 150ns   | high-time for sending a `1`
74
| T~0L~                 | 0.8μs +/- 150ns   | low-time for sending a `1`
75
| T~1H~                 | 0.85μs +/- 150ns  | high-time for sending a `0`
76
| T~1L~                 | 0.45μs +/- 150 ns | low-time for sending a `0`
77
| RESET                 | Above 50μs        | low-time for sending a RESET command
78
|=======================
79
 
80
 
81
**Timing Configuration**
82
 
83 64 zero_gravi
The basic carrier frequency (800kHz for the WS2812 LEDs) is configured via a 3-bit main clock prescaler (_NEOLED_CTRL_PRSCx_, see table below)
84
that scales the main processor clock f~main~ and a 5-bit cycle multiplier _NEOLED_CTRL_T_TOT_x_.
85 60 zero_gravi
 
86
.NEOLED prescaler configuration
87
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
88
[options="header",grid="rows"]
89
|=======================
90 64 zero_gravi
| **`NEOLED_CTRL_PRSCx`**     | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
91 60 zero_gravi
| Resulting `clock_prescaler` |       2 |       4 |       8 |      64 |     128 |    1024 |    2048 |    4096
92
|=======================
93
 
94
The duty-cycles (or more precisely: the high- and low-times for sending either a '1' bit or a '0' bit) are
95 64 zero_gravi
defined via the 5-bit _NEOLED_CTRL_T_ONE_H_x_ and _NEOLED_CTRL_T_ZERO_H_x_ values, respectively. These programmable
96 60 zero_gravi
timing constants allow to adapt the interface for a wide variety of smart LED protocol (for example WS2812 vs.
97
WS2811).
98
 
99 62 zero_gravi
 
100 65 zero_gravi
**Timing Configuration - Example (WS2812)**
101 60 zero_gravi
 
102
Generate the base clock f~TX~ for the NEOLED TX engine:
103
 
104
* processor clock f~main~ = 100 MHz
105 64 zero_gravi
* _NEOLED_CTRL_PRSCx_ = `0b001` = f~main~ / 4
106 60 zero_gravi
 
107
_**f~TX~**_ = _f~main~[Hz]_ / `clock_prescaler` = 100MHz / 4 = 25MHz
108
 
109
_**T~TX~**_ = 1 / _**f~TX~**_ = 40ns
110
 
111
Generate carrier period (T~carrier~) and *high-times* (duty cycle) for sending `0` (T~0H~) and `1` (T~1H~) bits:
112
 
113 64 zero_gravi
* _NEOLED_CTRL_T_TOT_ = `0b11110` (= decimal 30)
114
* _NEOLED_CTRL_T_ZERO_H_ = `0b01010` (= decimal 10)
115
* _NEOLED_CTRL_T_ONE_H_ = `0b10100` (= decimal 20)
116 60 zero_gravi
 
117 64 zero_gravi
_**T~carrier~**_ = _**T~TX~**_ * _NEOLED_CTRL_T_TOT_ = 40ns * 30 = 1.4µs
118 60 zero_gravi
 
119 64 zero_gravi
_**T~0H~**_ = _**T~TX~**_ * _NEOLED_CTRL_T_ZERO_H_ = 40ns * 10 = 0.4µs
120 60 zero_gravi
 
121 64 zero_gravi
_**T~1H~**_ = _**T~TX~**_ * _NEOLED_CTRL_T_ONE_H_ = 40ns * 20 = 0.8µs
122 60 zero_gravi
 
123
[TIP]
124
The NEOLED SW driver library (`neorv32_neoled.h`) provides a simplified configuration
125
function that configures all timing parameters for driving WS2812 LEDs based on the processor
126 62 zero_gravi
clock frequency.
127 60 zero_gravi
 
128
 
129
**TX Data FIFO**
130
 
131 62 zero_gravi
The interface features a TX data buffer (a FIFO) to allow more CPU-independent operation. The buffer depth
132
is configured via the _IO_NEOLED_TX_FIFO_ top generic (default = 1 entry).
133 64 zero_gravi
The FIFO size configuration can be read via the _NEOLED_CTRL_BUFS_x_
134 62 zero_gravi
control register bits, which result log2(_IO_NEOLED_TX_FIFO_).
135 60 zero_gravi
 
136 64 zero_gravi
When writing data to the `DATA` register the data is automatically written to the TX buffer. Whenever
137 60 zero_gravi
data is available in the buffer the serial transmission engine will take it and transmit it to the LEDs.
138
The data transfer size (_NEOLED_MODE_EN_) can be modified at every time since this control register bit is also buffered
139
in the FIFO. This allows to arbitrarily mixing RGB and RGBW LEDs in the chain.
140
 
141 64 zero_gravi
Software can check the FIFO fill level via the control register's _NEOLED_CTRL_TX_EMPTY_, _NEOLED_CTRL_TX_HALF_
142
and _NEOLED_CTRL_TX_FULL_ flags. The _NEOLED_CTRL_TX_BUSY_ flags provides additional information if the the TX unit is
143 62 zero_gravi
still busy sending data.
144
 
145 60 zero_gravi
[WARNING]
146 64 zero_gravi
Please note that the timing configurations (_NEOLED_CTRL_PRSCx_, _NEOLED_CTRL_T_TOT_x_,
147
_NEOLED_CTRL_T_ONE_H_x_ and _NEOLED_CTRL_T_ZERO_H_x_) are **NOT** stored to the buffer. Changing
148 62 zero_gravi
these value while the buffer is not empty or the TX engine is still busy will cause data corruption.
149 60 zero_gravi
 
150
 
151 62 zero_gravi
** Strobe Command ("RESET") **
152 60 zero_gravi
 
153 62 zero_gravi
According to the WS2812 specs the data written to the LED's shift registers is strobed to the actual PWM driver
154
registers when the data line is low for 50μs ("RESET" command, see table above). This can be implemented
155
using busy-wait for at least 50μs. Obviously, this concept wastes a lot of processing power.
156 60 zero_gravi
 
157 62 zero_gravi
To circumvent this, the NEOLED module provides an option to automatically issue an idle time for creating the RESET
158 64 zero_gravi
command. If the _NEOLED_CTRL_STROBE_ control register bit is set, _all_ data written to the data FIFO (via `DATA`,
159 62 zero_gravi
the actually written data is irrelevant) will trigger an idle phase (`neoled_o` = zero) of 127 periods (= _**T~carrier~**_).
160
This idle time will cause the LEDs to strobe the color data into the PWM driver registers.
161 60 zero_gravi
 
162 65 zero_gravi
Since the _NEOLED_CTRL_STROBE_ flag is also buffered in the TX buffer, the RESET command is treated just as another
163 62 zero_gravi
data word being written to the TX buffer making busy wait concepts obsolete and allowing maximum refresh rates.
164 60 zero_gravi
 
165
 
166 62 zero_gravi
**Interrupt**
167
 
168 65 zero_gravi
The NEOLED modules features a single interrupt that becomes pending based on the current TX buffer fill level.
169
The interrupt can only become pending if the NEOLED module is enabled. The specific interrupt condition
170
is configured via the _NEOLED_CTRL_IRQ_CONF_ in the control register `NEORV32_NEOLED.CTRL`.
171 62 zero_gravi
 
172 65 zero_gravi
If _NEOLED_CTRL_IRQ_CONF_ is cleared, an interrupt is generated whenever the TX FIFO is _less than half-full_.
173
In this case software can write up to _IO_NEOLED_TX_FIFO_/2 new data words to `DATA` without checking the FIFO
174
status flags. The interrupt request is cleared whenever the FIFO fill level is above _half-full_ level or if
175
the NEOLED module is disabled.
176 62 zero_gravi
 
177 65 zero_gravi
If _NEOLED_CTRL_IRQ_CONF_ is set, an interrupt is generated whenever the TX FIFO is _empty_. The interrupt
178
request is cleared again when the FIFO contains at least one data word.
179 62 zero_gravi
 
180 65 zero_gravi
[NOTE]
181
The _NEOLED_CTRL_IRQ_CONF_ is hardwired to one if _IO_NEOLED_TX_FIFO_ = 1 (-> IRQ if FIFO is empty).
182
 
183
If the FIFO is configured to contain only a single entry (_IO_NEOLED_TX_FIFO_ = 1) the interrupt
184
will become pending if the FIFO (which is just a single register providing simple _double-buffering_) is empty.
185
 
186
 
187 60 zero_gravi
<<<
188 64 zero_gravi
.NEOLED register map (`struct NEORV32_NEOLED`)
189 60 zero_gravi
[cols="<4,<5,<9,^2,<9"]
190
[options="header",grid="all"]
191
|=======================
192
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
193 65 zero_gravi
.30+<| `0xffffffd8` .30+<| `NEORV32_NEOLED.CTRL` <|`0` _NEOLED_CTRL_EN_          ^| r/w <| NEOLED enable
194
                                                 <|`1` _NEOLED_CTRL_MODE_        ^| r/w <| data transfer size; `0`=24-bit; `1`=32-bit
195
                                                 <|`2` _NEOLED_CTRL_STROBE_      ^| r/w <| `0`=send normal color data; `1`=send RESET command on data write access
196
                                                 <|`3` _NEOLED_CTRL_PRSC0_       ^| r/w <| 3-bit clock prescaler, bit 0
197
                                                 <|`4` _NEOLED_CTRL_PRSC1_       ^| r/w <| 3-bit clock prescaler, bit 1
198
                                                 <|`5` _NEOLED_CTRL_PRSC2_       ^| r/w <| 3-bit clock prescaler, bit 2
199
                                                 <|`6` _NEOLED_CTRL_BUFS0_       ^| r/- .4+<| 4-bit log2(_IO_NEOLED_TX_FIFO_)
200
                                                 <|`7` _NEOLED_CTRL_BUFS1_       ^| r/-
201
                                                 <|`8` _NEOLED_CTRL_BUFS2_       ^| r/-
202
                                                 <|`9` _NEOLED_CTRL_BUFS3_       ^| r/-
203
                                                 <|`10` _NEOLED_CTRL_T_TOT_0_    ^| r/w .5+<| 5-bit pulse clock ticks per total single-bit period (T~total~)
204
                                                 <|`11` _NEOLED_CTRL_T_TOT_1_    ^| r/w
205
                                                 <|`12` _NEOLED_CTRL_T_TOT_2_    ^| r/w
206
                                                 <|`13` _NEOLED_CTRL_T_TOT_3_    ^| r/w
207
                                                 <|`14` _NEOLED_CTRL_T_TOT_4_    ^| r/w
208
                                                 <|`15` _NEOLED_CTRL_T_ZERO_H_0_ ^| r/w .5+<| 5-bit pulse clock ticks per high-time for sending a zero-bit (T~0H~)
209
                                                 <|`16` _NEOLED_CTRL_T_ZERO_H_1_ ^| r/w
210
                                                 <|`17` _NEOLED_CTRL_T_ZERO_H_2_ ^| r/w
211
                                                 <|`18` _NEOLED_CTRL_T_ZERO_H_3_ ^| r/w
212
                                                 <|`19` _NEOLED_CTRL_T_ZERO_H_4_ ^| r/w
213
                                                 <|`20` _NEOLED_CTRL_T_ONE_H_0_  ^| r/w .5+<| 5-bit pulse clock ticks per high-time for sending a one-bit (T~1H~)
214
                                                 <|`21` _NEOLED_CTRL_T_ONE_H_1_  ^| r/w
215
                                                 <|`22` _NEOLED_CTRL_T_ONE_H_2_  ^| r/w
216
                                                 <|`23` _NEOLED_CTRL_T_ONE_H_3_  ^| r/w
217
                                                 <|`24` _NEOLED_CTRL_T_ONE_H_4_  ^| r/w
218
                                                 <|`27` _NEOLED_CTRL_IRQ_CONF_   ^| r/w <| TX FIFO interrupt configuration: `0`=IRQ if FIFO is less than half-full, `1`=IRQ if FIFO is empty
219
                                                 <|`28` _NEOLED_CTRL_TX_EMPTY_   ^| r/- <| TX FIFO is empty
220
                                                 <|`29` _NEOLED_CTRL_TX_HALF_    ^| r/- <| TX FIFO is _at least_ half full
221
                                                 <|`30` _NEOLED_CTRL_TX_FULL_    ^| r/- <| TX FIFO is full
222
                                                 <|`31` _NEOLED_CTRL_TX_BUSY_    ^| r/- <| TX serial engine is busy when set
223 64 zero_gravi
| `0xffffffdc` | `NEORV32_NEOLED.DATA` <|`31:0` / `23:0` ^| -/w <| TX data (32-/24-bit)
224 60 zero_gravi
|=======================

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.