Line 28... |
Line 28... |
|
|
The interface provides a single 1-bit output `neoled_o` to drive an arbitrary number of cascaded LEDs. Since the
|
The interface provides a single 1-bit output `neoled_o` to drive an arbitrary number of cascaded LEDs. Since the
|
NEOLED module provides 24-bit and 32-bit operating modes, a mixed setup with RGB LEDs (24-bit color)
|
NEOLED module provides 24-bit and 32-bit operating modes, a mixed setup with RGB LEDs (24-bit color)
|
and RGBW LEDs (32-bit color including a dedicated white LED chip) is possible.
|
and RGBW LEDs (32-bit color including a dedicated white LED chip) is possible.
|
|
|
**Theory of Operation – NEOLED Module**
|
**Theory of Operation - NEOLED Module**
|
|
|
The NEOLED modules provides two accessible interface registers: the control register `CTRL` and the
|
The NEOLED modules provides two accessible interface registers: the control register `CTRL` and the
|
TX data register `DATA`. The NEOLED module is globally enabled via the control register's
|
TX data register `DATA`. The NEOLED module is globally enabled via the control register's
|
_NEOLED_CTRL_EN_ bit. Clearing this bit will terminate any current operation, clear the TX buffer, reset the module
|
_NEOLED_CTRL_EN_ bit. Clearing this bit will terminate any current operation, clear the TX buffer, reset the module
|
and set the `neoled_o` output to zero. The precise timing (implementing the **WS2812** protocol) and transmission
|
and set the `neoled_o` output to zero. The precise timing (implementing the **WS2812** protocol) and transmission
|
Line 53... |
Line 53... |
|
|
The mode bit can be configured before writing each new data word in order to support
|
The mode bit can be configured before writing each new data word in order to support
|
an arbitrary setup of RGB and RGBW LEDs.
|
an arbitrary setup of RGB and RGBW LEDs.
|
|
|
|
|
**Theory of Operation – Protocol**
|
**Theory of Operation - Protocol**
|
|
|
The interface of the WS2812 LEDs uses an 800kHz carrier signal. Data is transmitted in a serial manner
|
The interface of the WS2812 LEDs uses an 800kHz carrier signal. Data is transmitted in a serial manner
|
starting with LSB-first. The intensity for each R, G & B (& W) LED chip (= color code) is defined via an 8-bit
|
starting with LSB-first. The intensity for each R, G & B (& W) LED chip (= color code) is defined via an 8-bit
|
value. The actual data bits are transferred by modifying the duty cycle of the signal (the timings for the
|
value. The actual data bits are transferred by modifying the duty cycle of the signal (the timings for the
|
WS2812 are shown below). A RESET command is "send" by pulling the data line LOW for at least 50μs.
|
WS2812 are shown below). A RESET command is "send" by pulling the data line LOW for at least 50μs.
|
Line 95... |
Line 95... |
defined via the 5-bit _NEOLED_CTRL_T_ONE_H_x_ and _NEOLED_CTRL_T_ZERO_H_x_ values, respectively. These programmable
|
defined via the 5-bit _NEOLED_CTRL_T_ONE_H_x_ and _NEOLED_CTRL_T_ZERO_H_x_ values, respectively. These programmable
|
timing constants allow to adapt the interface for a wide variety of smart LED protocol (for example WS2812 vs.
|
timing constants allow to adapt the interface for a wide variety of smart LED protocol (for example WS2812 vs.
|
WS2811).
|
WS2811).
|
|
|
|
|
**Timing Configuration – Example (WS2812)**
|
**Timing Configuration - Example (WS2812)**
|
|
|
Generate the base clock f~TX~ for the NEOLED TX engine:
|
Generate the base clock f~TX~ for the NEOLED TX engine:
|
|
|
* processor clock f~main~ = 100 MHz
|
* processor clock f~main~ = 100 MHz
|
* _NEOLED_CTRL_PRSCx_ = `0b001` = f~main~ / 4
|
* _NEOLED_CTRL_PRSCx_ = `0b001` = f~main~ / 4
|
Line 157... |
Line 157... |
To circumvent this, the NEOLED module provides an option to automatically issue an idle time for creating the RESET
|
To circumvent this, the NEOLED module provides an option to automatically issue an idle time for creating the RESET
|
command. If the _NEOLED_CTRL_STROBE_ control register bit is set, _all_ data written to the data FIFO (via `DATA`,
|
command. If the _NEOLED_CTRL_STROBE_ control register bit is set, _all_ data written to the data FIFO (via `DATA`,
|
the actually written data is irrelevant) will trigger an idle phase (`neoled_o` = zero) of 127 periods (= _**T~carrier~**_).
|
the actually written data is irrelevant) will trigger an idle phase (`neoled_o` = zero) of 127 periods (= _**T~carrier~**_).
|
This idle time will cause the LEDs to strobe the color data into the PWM driver registers.
|
This idle time will cause the LEDs to strobe the color data into the PWM driver registers.
|
|
|
Since the _NEOLED_CTRL_STROBE_ flag is also buffered in the TX buffer, the RESET command is treated as just another
|
Since the _NEOLED_CTRL_STROBE_ flag is also buffered in the TX buffer, the RESET command is treated just as another
|
data word being written to the TX buffer making busy wait concepts obsolete and allowing maximum refresh rates.
|
data word being written to the TX buffer making busy wait concepts obsolete and allowing maximum refresh rates.
|
|
|
|
|
**Interrupt**
|
**Interrupt**
|
|
|
The NEOLED modules features a single interrupt that is triggered whenever the TX FIFO's fill level
|
The NEOLED modules features a single interrupt that becomes pending based on the current TX buffer fill level.
|
falls below _half-full_ level. In this case software can write up to _IO_NEOLED_TX_FIFO_/2 new data
|
The interrupt can only become pending if the NEOLED module is enabled. The specific interrupt condition
|
words to `DATA` without checking the FIFO status flags.
|
is configured via the _NEOLED_CTRL_IRQ_CONF_ in the control register `NEORV32_NEOLED.CTRL`.
|
|
|
|
If _NEOLED_CTRL_IRQ_CONF_ is cleared, an interrupt is generated whenever the TX FIFO is _less than half-full_.
|
|
In this case software can write up to _IO_NEOLED_TX_FIFO_/2 new data words to `DATA` without checking the FIFO
|
|
status flags. The interrupt request is cleared whenever the FIFO fill level is above _half-full_ level or if
|
|
the NEOLED module is disabled.
|
|
|
This highly relaxes time constraints for sending a continuous data stream to the LEDs
|
If _NEOLED_CTRL_IRQ_CONF_ is set, an interrupt is generated whenever the TX FIFO is _empty_. The interrupt
|
(as an idle time beyond 50μs will trigger the LED's a RESET command).
|
request is cleared again when the FIFO contains at least one data word.
|
|
|
|
[NOTE]
|
|
The _NEOLED_CTRL_IRQ_CONF_ is hardwired to one if _IO_NEOLED_TX_FIFO_ = 1 (-> IRQ if FIFO is empty).
|
|
|
|
If the FIFO is configured to contain only a single entry (_IO_NEOLED_TX_FIFO_ = 1) the interrupt
|
|
will become pending if the FIFO (which is just a single register providing simple _double-buffering_) is empty.
|
|
|
|
|
|
|
.NEOLED register map (`struct NEORV32_NEOLED`)
|
.NEOLED register map (`struct NEORV32_NEOLED`)
|
[cols="<4,<5,<9,^2,<9"]
|
[cols="<4,<5,<9,^2,<9"]
|
[options="header",grid="all"]
|
[options="header",grid="all"]
|
|=======================
|
|=======================
|
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
|
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
|
.25+<| `0xffffffd8` .25+<| `NEORV32_NEOLED.CTRL` <|`0` _NEOLED_CTRL_EN_ ^| r/w <| NEOLED enable
|
.30+<| `0xffffffd8` .30+<| `NEORV32_NEOLED.CTRL` <|`0` _NEOLED_CTRL_EN_ ^| r/w <| NEOLED enable
|
<|`1` _NEOLED_CTRL_MODE_ ^| r/w <| data transfer size; `0`=24-bit; `1`=32-bit
|
<|`1` _NEOLED_CTRL_MODE_ ^| r/w <| data transfer size; `0`=24-bit; `1`=32-bit
|
<|`2` _NEOLED_CTRL_STROBE_ ^| r/w <| `0`=send normal color data; `1`=send RESET command on data write access
|
<|`2` _NEOLED_CTRL_STROBE_ ^| r/w <| `0`=send normal color data; `1`=send RESET command on data write access
|
<|`3` _NEOLED_CTRL_PRSC0_ ^| r/w <| 3-bit clock prescaler, bit 0
|
<|`3` _NEOLED_CTRL_PRSC0_ ^| r/w <| 3-bit clock prescaler, bit 0
|
<|`4` _NEOLED_CTRL_PRSC1_ ^| r/w <| 3-bit clock prescaler, bit 1
|
<|`4` _NEOLED_CTRL_PRSC1_ ^| r/w <| 3-bit clock prescaler, bit 1
|
<|`5` _NEOLED_CTRL_PRSC2_ ^| r/w <| 3-bit clock prescaler, bit 2
|
<|`5` _NEOLED_CTRL_PRSC2_ ^| r/w <| 3-bit clock prescaler, bit 2
|
Line 192... |
Line 203... |
<|`10` _NEOLED_CTRL_T_TOT_0_ ^| r/w .5+<| 5-bit pulse clock ticks per total single-bit period (T~total~)
|
<|`10` _NEOLED_CTRL_T_TOT_0_ ^| r/w .5+<| 5-bit pulse clock ticks per total single-bit period (T~total~)
|
<|`11` _NEOLED_CTRL_T_TOT_1_ ^| r/w
|
<|`11` _NEOLED_CTRL_T_TOT_1_ ^| r/w
|
<|`12` _NEOLED_CTRL_T_TOT_2_ ^| r/w
|
<|`12` _NEOLED_CTRL_T_TOT_2_ ^| r/w
|
<|`13` _NEOLED_CTRL_T_TOT_3_ ^| r/w
|
<|`13` _NEOLED_CTRL_T_TOT_3_ ^| r/w
|
<|`14` _NEOLED_CTRL_T_TOT_4_ ^| r/w
|
<|`14` _NEOLED_CTRL_T_TOT_4_ ^| r/w
|
<|`20` _NEOLED_CTRL_ONE_H_0_ ^| r/w .5+<| 5-bit pulse clock ticks per high-time for sending a one-bit (T~H1~)
|
<|`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~)
|
<|`21` _NEOLED_CTRL_ONE_H_1_ ^| r/w
|
<|`16` _NEOLED_CTRL_T_ZERO_H_1_ ^| r/w
|
<|`22` _NEOLED_CTRL_ONE_H_2_ ^| r/w
|
<|`17` _NEOLED_CTRL_T_ZERO_H_2_ ^| r/w
|
<|`23` _NEOLED_CTRL_ONE_H_3_ ^| r/w
|
<|`18` _NEOLED_CTRL_T_ZERO_H_3_ ^| r/w
|
<|`24` _NEOLED_CTRL_ONE_H_4_ ^| r/w
|
<|`19` _NEOLED_CTRL_T_ZERO_H_4_ ^| r/w
|
<|`30` _NEOLED_CTRL_TX_STATUS_ ^| r/- <| transmit engine busy when `1`
|
<|`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~)
|
<|`31` _NEOLED_CTRL_TX_EMPTY_ ^| r/- <| TX FIFO is empty
|
<|`21` _NEOLED_CTRL_T_ONE_H_1_ ^| r/w
|
<|`31` _NEOLED_CTRL_TX_HALF_ ^| r/- <| TX FIFO is _at least_ half full
|
<|`22` _NEOLED_CTRL_T_ONE_H_2_ ^| r/w
|
<|`31` _NEOLED_CTRL_TX_FULL_ ^| r/- <| TX FIFO is full
|
<|`23` _NEOLED_CTRL_T_ONE_H_3_ ^| r/w
|
|
<|`24` _NEOLED_CTRL_T_ONE_H_4_ ^| r/w
|
|
<|`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
|
|
<|`28` _NEOLED_CTRL_TX_EMPTY_ ^| r/- <| TX FIFO is empty
|
|
<|`29` _NEOLED_CTRL_TX_HALF_ ^| r/- <| TX FIFO is _at least_ half full
|
|
<|`30` _NEOLED_CTRL_TX_FULL_ ^| r/- <| TX FIFO is full
|
<|`31` _NEOLED_CTRL_TX_BUSY_ ^| r/- <| TX serial engine is busy when set
|
<|`31` _NEOLED_CTRL_TX_BUSY_ ^| r/- <| TX serial engine is busy when set
|
| `0xffffffdc` | `NEORV32_NEOLED.DATA` <|`31:0` / `23:0` ^| -/w <| TX data (32-/24-bit)
|
| `0xffffffdc` | `NEORV32_NEOLED.DATA` <|`31:0` / `23:0` ^| -/w <| TX data (32-/24-bit)
|
|=======================
|
|=======================
|