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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [docs/] [datasheet/] [soc_neoled.adoc] - Diff between revs 62 and 64

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 62 Rev 64
Line 30... Line 30...
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 _NEOLED_CT_ and the
The NEOLED modules provides two accessible interface registers: the control register `CTRL` and the
TX data register _NEOLED_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_CT_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
mode are fully programmable via the _NEOLED_CT_ register to provide maximum flexibility.
mode are fully programmable via the `CTRL` register to provide maximum flexibility.
 
 
 
 
**RGB / RGBW Configuration**
**RGB / RGBW Configuration**
 
 
NeoPixel are available in two "color" version: LEDs with three chips providing RGB color and LEDs with
NeoPixel are available in two "color" version: LEDs with three chips providing RGB color and LEDs with
Line 46... Line 46...
LED chip is defined via an 8-bit value the RGB LEDs require a frame of 24-bit per module and the RGBW
LED chip is defined via an 8-bit value the RGB LEDs require a frame of 24-bit per module and the RGBW
LEDs require a frame of 32-bit per module.
LEDs require a frame of 32-bit per module.
 
 
The data transfer quantity of the NEOLED module can be configured via the _NEOLED_MODE_EN_ control
The data transfer quantity of the NEOLED module can be configured via the _NEOLED_MODE_EN_ control
register bit. If this bit is cleared, the NEOLED interface operates in 24-bit mode and will transmit bits `23:0` of
register bit. If this bit is cleared, the NEOLED interface operates in 24-bit mode and will transmit bits `23:0` of
the data written to _NEOLED_DATA_ to the LEDs. If _NEOLED_MODE_EN_ is set, the NEOLED interface operates in 32-bit
the data written to `DATA` to the LEDs. If _NEOLED_MODE_EN_ is set, the NEOLED interface operates in 32-bit
mode and will transmit bits `31:0` of the data written to _NEOLED_DATA_ to the LEDs.
mode and will transmit bits `31:0` of the data written to `DATA` to the LEDs.
 
 
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.
 
 
 
 
Line 78... Line 78...
|=======================
|=======================
 
 
 
 
**Timing Configuration**
**Timing Configuration**
 
 
The basic carrier frequency (800kHz for the WS2812 LEDs) is configured via a 3-bit main clock prescaler (_NEOLED_CT_PRSCx_, see table below)
The basic carrier frequency (800kHz for the WS2812 LEDs) is configured via a 3-bit main clock prescaler (_NEOLED_CTRL_PRSCx_, see table below)
that scales the main processor clock f~main~ and a 5-bit cycle multiplier _NEOLED_CT_T_TOT_x_.
that scales the main processor clock f~main~ and a 5-bit cycle multiplier _NEOLED_CTRL_T_TOT_x_.
 
 
.NEOLED prescaler configuration
.NEOLED prescaler configuration
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
[options="header",grid="rows"]
[options="header",grid="rows"]
|=======================
|=======================
| **`NEOLED_CT_PRSCx`**       | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
| **`NEOLED_CTRL_PRSCx`**     | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
| Resulting `clock_prescaler` |       2 |       4 |       8 |      64 |     128 |    1024 |    2048 |    4096
| Resulting `clock_prescaler` |       2 |       4 |       8 |      64 |     128 |    1024 |    2048 |    4096
|=======================
|=======================
 
 
The duty-cycles (or more precisely: the high- and low-times for sending either a '1' bit or a '0' bit) are
The duty-cycles (or more precisely: the high- and low-times for sending either a '1' bit or a '0' bit) are
defined via the 5-bit _NEOLED_CT_T_ONE_H_x_ and _NEOLED_CT_T_ZERO_H_x_ values, respecively. 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_CT_PRSCx_ = `0b001` = f~main~ / 4
* _NEOLED_CTRL_PRSCx_ = `0b001` = f~main~ / 4
 
 
_**f~TX~**_ = _f~main~[Hz]_ / `clock_prescaler` = 100MHz / 4 = 25MHz
_**f~TX~**_ = _f~main~[Hz]_ / `clock_prescaler` = 100MHz / 4 = 25MHz
 
 
_**T~TX~**_ = 1 / _**f~TX~**_ = 40ns
_**T~TX~**_ = 1 / _**f~TX~**_ = 40ns
 
 
Generate carrier period (T~carrier~) and *high-times* (duty cycle) for sending `0` (T~0H~) and `1` (T~1H~) bits:
Generate carrier period (T~carrier~) and *high-times* (duty cycle) for sending `0` (T~0H~) and `1` (T~1H~) bits:
 
 
* _NEOLED_CT_T_TOT_ = `0b11110` (= decimal 30)
* _NEOLED_CTRL_T_TOT_ = `0b11110` (= decimal 30)
* _NEOLED_CT_T_ZERO_H_ = `0b01010` (= decimal 10)
* _NEOLED_CTRL_T_ZERO_H_ = `0b01010` (= decimal 10)
* _NEOLED_CT_T_ONE_H_ = `0b10100` (= decimal 20)
* _NEOLED_CTRL_T_ONE_H_ = `0b10100` (= decimal 20)
 
 
_**T~carrier~**_ = _**T~TX~**_ * _NEOLED_CT_T_TOT_ = 40ns * 30 = 1.4µs
_**T~carrier~**_ = _**T~TX~**_ * _NEOLED_CTRL_T_TOT_ = 40ns * 30 = 1.4µs
 
 
_**T~0H~**_ = _**T~TX~**_ * _NEOLED_CT_T_ZERO_H_ = 40ns * 10 = 0.4µs
_**T~0H~**_ = _**T~TX~**_ * _NEOLED_CTRL_T_ZERO_H_ = 40ns * 10 = 0.4µs
 
 
_**T~1H~**_ = _**T~TX~**_ * _NEOLED_CT_T_ONE_H_ = 40ns * 20 = 0.8µs
_**T~1H~**_ = _**T~TX~**_ * _NEOLED_CTRL_T_ONE_H_ = 40ns * 20 = 0.8µs
 
 
[TIP]
[TIP]
The NEOLED SW driver library (`neorv32_neoled.h`) provides a simplified configuration
The NEOLED SW driver library (`neorv32_neoled.h`) provides a simplified configuration
function that configures all timing parameters for driving WS2812 LEDs based on the processor
function that configures all timing parameters for driving WS2812 LEDs based on the processor
clock frequency.
clock frequency.
Line 128... Line 128...
 
 
**TX Data FIFO**
**TX Data FIFO**
 
 
The interface features a TX data buffer (a FIFO) to allow more CPU-independent operation. The buffer depth
The interface features a TX data buffer (a FIFO) to allow more CPU-independent operation. The buffer depth
is configured via the _IO_NEOLED_TX_FIFO_ top generic (default = 1 entry).
is configured via the _IO_NEOLED_TX_FIFO_ top generic (default = 1 entry).
The FIFO size configuration can be read via the _NEOLED_CT_BUFS_x_
The FIFO size configuration can be read via the _NEOLED_CTRL_BUFS_x_
control register bits, which result log2(_IO_NEOLED_TX_FIFO_).
control register bits, which result log2(_IO_NEOLED_TX_FIFO_).
 
 
When writing data to the _NEOLED_DATA_ register the data is automatically written to the TX buffer. Whenever
When writing data to the `DATA` register the data is automatically written to the TX buffer. Whenever
data is available in the buffer the serial transmission engine will take it and transmit it to the LEDs.
data is available in the buffer the serial transmission engine will take it and transmit it to the LEDs.
The data transfer size (_NEOLED_MODE_EN_) can be modified at every time since this control register bit is also buffered
The data transfer size (_NEOLED_MODE_EN_) can be modified at every time since this control register bit is also buffered
in the FIFO. This allows to arbitrarily mixing RGB and RGBW LEDs in the chain.
in the FIFO. This allows to arbitrarily mixing RGB and RGBW LEDs in the chain.
 
 
Software can check the FIFO fill level via the control register's _NEOLED_CT_TX_EMPTY_, _NEOLED_CT_TX_HALF_
Software can check the FIFO fill level via the control register's _NEOLED_CTRL_TX_EMPTY_, _NEOLED_CTRL_TX_HALF_
and _NEOLED_CT_TX_FULL_ flags. The _NEOLED_CT_TX_BUSY_ flags provides additional information if the the TX unit is
and _NEOLED_CTRL_TX_FULL_ flags. The _NEOLED_CTRL_TX_BUSY_ flags provides additional information if the the TX unit is
still busy sending data.
still busy sending data.
 
 
[WARNING]
[WARNING]
Please note that the timing configurations (_NEOLED_CT_PRSCx_, _NEOLED_CT_T_TOT_x_,
Please note that the timing configurations (_NEOLED_CTRL_PRSCx_, _NEOLED_CTRL_T_TOT_x_,
_NEOLED_CT_T_ONE_H_x_ and _NEOLED_CT_T_ZERO_H_x_) are **NOT** stored to the buffer. Changing
_NEOLED_CTRL_T_ONE_H_x_ and _NEOLED_CTRL_T_ZERO_H_x_) are **NOT** stored to the buffer. Changing
these value while the buffer is not empty or the TX engine is still busy will cause data corruption.
these value while the buffer is not empty or the TX engine is still busy will cause data corruption.
 
 
 
 
** Strobe Command ("RESET") **
** Strobe Command ("RESET") **
 
 
According to the WS2812 specs the data written to the LED's shift registers is strobed to the actual PWM driver
According to the WS2812 specs the data written to the LED's shift registers is strobed to the actual PWM driver
registers when the data line is low for 50μs ("RESET" command, see table above). This can be implemented
registers when the data line is low for 50μs ("RESET" command, see table above). This can be implemented
using busy-wait for at least 50μs. Obviously, this concept wastes a lot of processing power.
using busy-wait for at least 50μs. Obviously, this concept wastes a lot of processing power.
 
 
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_CT_STROBE_ control register bit is set, _all_ data written to the data FIFO (via _NEOLED_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_CT_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 as just 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 is triggered whenever the TX FIFO's fill level
falls below _half-full_ level. In this case software can write up to _IO_NEOLED_TX_FIFO_/2 new data
falls below _half-full_ level. In this case software can write up to _IO_NEOLED_TX_FIFO_/2 new data
words to _NEOLED_DATA_ without checking the FIFO status flags.
words to `DATA` without checking the FIFO status flags.
 
 
This highly relaxes time constraints for sending a continuous data stream to the LEDs
This highly relaxes time constraints for sending a continuous data stream to the LEDs
(as an idle time beyond 50μs will trigger the LED's a RESET command).
(as an idle time beyond 50μs will trigger the LED's a RESET command).
 
 
 
 
 
 
.NEOLED register map
.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+<| _NEOLED_CT_ <|`0` _NEOLED_CT_EN_         ^| r/w <| NEOLED enable
.25+<| `0xffffffd8` .25+<| `NEORV32_NEOLED.CTRL` <|`0` _NEOLED_CTRL_EN_         ^| r/w <| NEOLED enable
                                       <|`1` _NEOLED_CT_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_CT_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_CT_PRSC0_      ^| r/w <| 3-bit clock prescaler, bit 0
                                                 <|`3` _NEOLED_CTRL_PRSC0_      ^| r/w <| 3-bit clock prescaler, bit 0
                                       <|`4` _NEOLED_CT_PRSC1_      ^| r/w <| 3-bit clock prescaler, bit 1
                                                 <|`4` _NEOLED_CTRL_PRSC1_      ^| r/w <| 3-bit clock prescaler, bit 1
                                       <|`5` _NEOLED_CT_PRSC2_      ^| r/w <| 3-bit clock prescaler, bit 2
                                                 <|`5` _NEOLED_CTRL_PRSC2_      ^| r/w <| 3-bit clock prescaler, bit 2
                                       <|`6` _NEOLED_CT_BUFS0_      ^| r/- .4+<| 4-bit log2(_IO_NEOLED_TX_FIFO_)
                                                 <|`6` _NEOLED_CTRL_BUFS0_      ^| r/- .4+<| 4-bit log2(_IO_NEOLED_TX_FIFO_)
                                       <|`7` _NEOLED_CT_BUFS1_      ^| r/-
                                                 <|`7` _NEOLED_CTRL_BUFS1_      ^| r/-
                                       <|`8` _NEOLED_CT_BUFS2_      ^| r/-
                                                 <|`8` _NEOLED_CTRL_BUFS2_      ^| r/-
                                       <|`9` _NEOLED_CT_BUFS3_      ^| r/-
                                                 <|`9` _NEOLED_CTRL_BUFS3_      ^| r/-
                                       <|`10` _NEOLED_CT_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_CT_T_TOT_1_   ^| r/w
                                                 <|`11` _NEOLED_CTRL_T_TOT_1_   ^| r/w
                                       <|`12` _NEOLED_CT_T_TOT_2_   ^| r/w
                                                 <|`12` _NEOLED_CTRL_T_TOT_2_   ^| r/w
                                       <|`13` _NEOLED_CT_T_TOT_3_   ^| r/w
                                                 <|`13` _NEOLED_CTRL_T_TOT_3_   ^| r/w
                                       <|`14` _NEOLED_CT_T_TOT_4_   ^| r/w
                                                 <|`14` _NEOLED_CTRL_T_TOT_4_   ^| r/w
                                       <|`20` _NEOLED_CT_ONE_H_0_   ^| r/w .5+<| 5-bit pulse clock ticks per high-time for sending a one-bit (T~H1~)
                                                 <|`20` _NEOLED_CTRL_ONE_H_0_   ^| r/w .5+<| 5-bit pulse clock ticks per high-time for sending a one-bit (T~H1~)
                                       <|`21` _NEOLED_CT_ONE_H_1_   ^| r/w
                                                 <|`21` _NEOLED_CTRL_ONE_H_1_   ^| r/w
                                       <|`22` _NEOLED_CT_ONE_H_2_   ^| r/w
                                                 <|`22` _NEOLED_CTRL_ONE_H_2_   ^| r/w
                                       <|`23` _NEOLED_CT_ONE_H_3_   ^| r/w
                                                 <|`23` _NEOLED_CTRL_ONE_H_3_   ^| r/w
                                       <|`24` _NEOLED_CT_ONE_H_4_   ^| r/w
                                                 <|`24` _NEOLED_CTRL_ONE_H_4_   ^| r/w
                                       <|`30` _NEOLED_CT_TX_STATUS_ ^| r/- <| transmit engine busy when `1`
                                                 <|`30` _NEOLED_CTRL_TX_STATUS_ ^| r/- <| transmit engine busy when `1`
                                       <|`31` _NEOLED_CT_TX_EMPTY_  ^| r/- <| TX FIFO is empty
                                                 <|`31` _NEOLED_CTRL_TX_EMPTY_  ^| r/- <| TX FIFO is empty
                                       <|`31` _NEOLED_CT_TX_HALF_   ^| r/- <| TX FIFO is _at least_ half full
                                                 <|`31` _NEOLED_CTRL_TX_HALF_   ^| r/- <| TX FIFO is _at least_ half full
                                       <|`31` _NEOLED_CT_TX_FULL_   ^| r/- <| TX FIFO is full
                                                 <|`31` _NEOLED_CTRL_TX_FULL_   ^| r/- <| TX FIFO is full
                                       <|`31` _NEOLED_CT_TX_BUSY_   ^| r/- <| TX serial engine is busy when set
                                                 <|`31` _NEOLED_CTRL_TX_BUSY_   ^| r/- <| TX serial engine is busy when set
| `0xffffffdc` | _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)
|=======================
|=======================

powered by: WebSVN 2.1.0

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