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

Subversion Repositories neorv32

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

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
| Top entity port:         | `neoled_o` | 1-bit serial data
12
| Configuration generics:  | _IO_NEOLED_EN_ | implement NEOLED when _true_
13
| CPU interrupts:          | fast IRQ channel 9 | NEOLED interrupt (see <<_processor_interrupts>>)
14
|=======================
15
 
16
**Theory of Operation**
17
 
18
The NEOLED module provides a dedicated interface for "smart RGB LEDs" like the WS2812 or WS2811.
19
These LEDs provide a single interface wire that uses an asynchronous serial protocol for transmitting color
20
data. Basically, data is transferred via LED-internal shift registers, which allows to cascade an unlimited
21
number of smart LEDs. The protocol provides a RESET command to strobe the transmitted data into the
22
LED PWM driver registers after data has shifted throughout all LEDs in a chain.
23
 
24
[NOTE]
25
The NEOLED interface is compatible to the "Adafruit Industries NeoPixel" products, which feature
26
WS2812 (or older WS2811) smart LEDs (see link:https://learn.adafruit.com/adafruit-neopixel-uberguide).
27
 
28
The interface provides a single 1-bit output `neoled_o` to drive an arbitrary number of LEDs. Since the
29
NEOLED module provides 24-bit and 32-bit operating modes, a mixed setup with RGB LEDs (24-bit color)
30
and RGBW LEDs (32-bit color including a dedicated white LED chip) is also possible.
31
 
32
**Theory of Operation – Protocol**
33
 
34
The interface of the WS2812 LEDs uses an 800kHz carrier signal. Data is transmitted in a serial manner
35
starting with LSB-first. The intensity for each R, G & B LED chip (= color code) is defined via an 8-bit
36
value. The actual data bits are transferred by modifying the duty cycle of the signal (the timings for the
37
WS2812 are shown below). A RESET command is "send" by pulling the data line LOW for at least 50μs.
38
 
39
.WS2812 bit-level protocol - taken from the "Adafruit NeoPixel Überguide"
40
image::neopixel.png[align=center]
41
 
42
.WS2812 interface timing
43
[cols="<2,<2,<6"]
44
[grid="all"]
45
|=======================
46
| T~total~ (T~carrier~) | 1.25μs +/- 300ns  | period for a single bit
47
| T~0H~                 | 0.4μs +/- 150ns   | high-time for sending a `1`
48
| T~0L~                 | 0.8μs +/- 150ns   | low-time for sending a `1`
49
| T~1H~                 | 0.85μs +/- 150ns  | high-time for sending a `0`
50
| T~1L~                 | 0.45μs +/- 150 ns | low-time for sending a `0`
51
| RESET                 | Above 50μs        | low-time for sending a RESET command
52
|=======================
53
 
54
**Theory of Operation – NEOLED Module**
55
 
56
The NEOLED modules provides two accessible interface register: the control register _NEOLED_CT_ and the
57
TX data register _NEOLED_DATA_. The NEOLED module is globally enabled via the control register's
58
_NEOLED_CT_EN_ bit. Clearing this bit will terminate any current operation, reset the module and
59
set the `neoled_o` output to zero. The precise timing (implementing the **WS2812** protocol) and transmission
60
mode are fully programmable via the _NEOLED_CT_ register to provide maximum flexibility.
61
 
62
**Timing Configuration**
63
 
64
The basic carrier frequency (800kHz for the WS2812 LEDs) is configured via a 3-bit main clock prescaler (_NEOLED_CT_PRSCx_, see table below)
65
that scales the main processor clock f~main~ and a 5-bit cycle multiplier _NEOLED_CT_T_TOT_x_.
66
 
67
.NEOLED prescaler configuration
68
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
69
[options="header",grid="rows"]
70
|=======================
71
| **`NEOLED_CT_PRSCx`**       | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
72
| Resulting `clock_prescaler` |       2 |       4 |       8 |      64 |     128 |    1024 |    2048 |    4096
73
|=======================
74
 
75
The duty-cycles (or more precisely: the high- and low-times for sending either a '1' bit or a '0' bit) are
76
defined via the 5-bit _NEOLED_CT_T_ONE_H_x_ and _NEOLED_CT_T_ZERO_H_x_ values, respecively. These programmable
77
timing constants allow to adapt the interface for a wide variety of smart LED protocol (for example WS2812 vs.
78
WS2811).
79
 
80
**Timing Configuration – Example (WS2812)**
81
 
82
Generate the base clock f~TX~ for the NEOLED TX engine:
83
 
84
* processor clock f~main~ = 100 MHz
85
* _NEOLED_CT_PRSCx_ = `0b001` = f~main~ / 4
86
 
87
_**f~TX~**_ = _f~main~[Hz]_ / `clock_prescaler` = 100MHz / 4 = 25MHz
88
 
89
_**T~TX~**_ = 1 / _**f~TX~**_ = 40ns
90
 
91
Generate carrier period (T~carrier~) and *high-times* (duty cycle) for sending `0` (T~0H~) and `1` (T~1H~) bits:
92
 
93
* _NEOLED_CT_T_TOT_ = `0b11110` (= decimal 30)
94
* _NEOLED_CT_T_ZERO_H_ = `0b01010` (= decimal 10)
95
* _NEOLED_CT_T_ONE_H_ = `0b10100` (= decimal 20)
96
 
97
_**T~carrier~**_ = _**T~TX~**_ * _NEOLED_CT_T_TOT_ = 40ns * 30 = 1.4µs
98
 
99
_**T~0H~**_ = _**T~TX~**_ * _NEOLED_CT_T_ZERO_H_ = 40ns * 10 = 0.4µs
100
 
101
_**T~1H~**_ = _**T~TX~**_ * _NEOLED_CT_T_ONE_H_ = 40ns * 20 = 0.8µs
102
 
103
[TIP]
104
The NEOLED SW driver library (`neorv32_neoled.h`) provides a simplified configuration
105
function that configures all timing parameters for driving WS2812 LEDs based on the processor
106
clock configuration.
107
 
108
**RGB / RGBW Configuration**
109
 
110
NeoPixel are available in two "color" version: LEDs with three chips providing RGB color and LEDs with
111
four chips providing RGB color plus a dedicated white LED chip (= RGBW). Since the intensity of every
112
LED chip is defined via an 8-bit value the RGB LEDs require a frame of 24-bit per module and the RGBW
113
LEDs require a frame of 32-bit per module.
114
 
115
The data transfer quantity of the NEOLED module can be configured via the _NEOLED_MODE_EN_ control
116
register bit. If this bit is cleared, the NEOLED interface operates in 24-bit mode and will transmit bits `23:0` of
117
the data written to _NEOLED_DATA_. If _NEOLED_MODE_EN_ is set, the NEOLED interface operates in 32-bit
118
mode and will transmit bits `31:0` of the data written to _NEOLED_DATA_.
119
 
120
**TX Data FIFO**
121
 
122
The interface features a TX data buffer (a FIFO) to allow CPU-independent operation. The buffer depth
123
is configured via the `tx_buffer_entries_c` constant (default = 4 entries) in the module's VHDL source
124
file `rtl/core/neorv32_neoled.vhd`. The current configuration can be read via the _NEOLED_CT_BUFS_x_
125
control register bits, which result log2(`tx_buffer_entries_c`).
126
 
127
When writing data to the _NEOLED_DATA_ register the data is automatically written to the TX buffer. Whenever
128
data is available in the buffer the serial transmission engine will take it and transmit it to the LEDs.
129
 
130
The data transfer size (_NEOLED_MODE_EN_) can be modified at every time since this control register bit is also buffered
131
in the FIFO. This allows to arbitrarily mixing RGB and RGBW LEDs in the chain.
132
 
133
[WARNING]
134
Please note that the timing configurations (_NEOLED_CT_PRSCx_, _NEOLED_CT_T_TOT_x_,
135
_NEOLED_CT_T_ONE_H_x_ and _NEOLED_CT_T_ZERO_H_x_) are NOT stored to the buffer. Changing
136
these value while the buffer is not empty or the TX engine is still sending will cause data corruption.
137
 
138
**Status Configuration**
139
 
140
The NEOLED modules features two read-only status bits in the control register: _NEOLED_CT_BUSY_ and
141
_NEOLED_CT_TX_STATUS_.
142
 
143
If the _NEOLED_CT_TX_STATUS_ is set the serial TX engine is still busy sending serial data to the LED stripes.
144
If the flag is cleared, the TX engine is idle and the serial data output `neoled_o` is set LOW.
145
 
146
The _NEOLED_CT_BUSY_ flag provides a programmable option to check for the TX buffer state. The control
147
register's _NEOLED_CT_BSCON_ bit is used to configure the "meaning" of the _NEOLED_CT_BUSY_ flag. The
148
condition for sending an interrupt request (IRQ) to the CPU is also configured via the _NEOLED_CT_BSCON_
149
bit.
150
 
151
[cols="^5,^8,^8"]
152
[options="header",grid="all"]
153
|=======================
154
| _NEOLED_CT_BSCON_ | _NEOLED_CT_BUSY_ | Sending an IRQ when ...
155
| 0 | the busy flag will clear if there **IS at least one free entry** in the TX buffer | the IRQ will fire if **at least one entry GETS free** in the TX buffer
156
| 1 | the busy flag will clear if the **whole TX buffer IS empty** | the IRQ will fire if the **whole TX buffer GETS empty**
157
|=======================
158
 
159
When _NEOLED_CT_BSCON_ is set, the CPU can write up to `tx_buffer_entries_c` of new data words to
160
_NEOLED_DATA_ without checking the busy flag _NEOLED_CT_BUSY_. This highly relaxes time constraints for
161
sending a continuous data stream to the LEDs (as an idle time beyond 50μs will trigger the LED's a RESET
162
command).
163
 
164
<<<
165
.NEOLED register map
166
[cols="<4,<5,<9,^2,<9"]
167
[options="header",grid="all"]
168
|=======================
169
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
170 61 zero_gravi
.22+<| `0xffffffd8` .22+<| _NEOLED_CT_ <|`0` _NEOLED_CT_EN_         ^| r/w <| NEOLED enable
171 60 zero_gravi
                                       <|`1` _NEOLED_CT_MODE_       ^| r/w <| data transfer size; `0`=24-bit; `1`=32-bit
172
                                       <|`2` _NEOLED_CT_BSCON_      ^| r/w <| busy flag / IRQ trigger configuration (see table above)
173
                                       <|`3` _NEOLED_CT_PRSC0_      ^| r/w <| 3-bit clock prescaler, bit 0
174
                                       <|`4` _NEOLED_CT_PRSC1_      ^| r/w <| 3-bit clock prescaler, bit 1
175
                                       <|`5` _NEOLED_CT_PRSC2_      ^| r/w <| 3-bit clock prescaler, bit 2
176
                                       <|`6` _NEOLED_CT_BUFS0_      ^| r/- .4+<| 4-bit log2(`tx_buffer_entries_c`)
177
                                       <|`7` _NEOLED_CT_BUFS1_      ^| r/-
178
                                       <|`8` _NEOLED_CT_BUFS2_      ^| r/-
179
                                       <|`9` _NEOLED_CT_BUFS3_      ^| r/-
180
                                       <|`10` _NEOLED_CT_T_TOT_0_   ^| r/w .5+| 5-bit pulse clock ticks per total single-bit period (T~total~)
181
                                       <|`11` _NEOLED_CT_T_TOT_1_   ^| r/w
182
                                       <|`12` _NEOLED_CT_T_TOT_2_   ^| r/w
183
                                       <|`13` _NEOLED_CT_T_TOT_3_   ^| r/w
184
                                       <|`14` _NEOLED_CT_T_TOT_4_   ^| r/w
185
                                       <|`20` _NEOLED_CT_ONE_H_0_   ^| r/w .5+<| 5-bit pulse clock ticks per high-time for sending a one-bit (T~H1~)
186
                                       <|`21` _NEOLED_CT_ONE_H_1_   ^| r/w
187
                                       <|`22` _NEOLED_CT_ONE_H_2_   ^| r/w
188
                                       <|`23` _NEOLED_CT_ONE_H_3_   ^| r/w
189
                                       <|`24` _NEOLED_CT_ONE_H_4_   ^| r/w
190
                                       <|`30` _NEOLED_CT_TX_STATUS_ ^| r/- <| transmit engine busy when `1`
191
                                       <|`31` _NEOLED_CT_BUSY_      ^| r/- <| busy / buffer status flag; configured via _NEOLED_CT_BSCON_ (see table above)
192
| `0xffffffdc` | _NEOLED_DATA_         <|`31:0` / `23:0`            ^| -/w <| TX data (32-/24-bit)
193
|=======================

powered by: WebSVN 2.1.0

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