Un anneau de LEDs WS2812B en feu
Avec mon contrôleur de LEDs adressables WS2812B, j’ai décidé de mettre le feu à mon anneau 12 LEDs, rien que ça…
Pour ce faire, voici le code en systemVerilog :
- top.sv :
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
module top (
input logic CLOCK_50, // Horloge 50MHz
output logic GPIO_WS2812B // À relier à l'entrée IN de l'anneau
);
localparam NB_LEDS = 12; // Anneau avec 12 LED adressables
localparam ON = 8'h20, // luminosité maxi=8'hff, mais /!\ la consommation si toutes les Leds sont allumées
OFF = 8'h00;
logic [7:0] red, green, blue;
logic [7:0] address; // Numéro de la LED entre 0 et NB_LEDS-1
logic load; // Chargement du registre si load=1
logic latch_n; // Déverrouillage et transfert du registre sur front descendant
logic [$clog2(NB_LEDS) - 1:0] num_led = 0; // Numéro de led en cours
logic [23:0] rgb;
logic [25:0] delay = 0;
assign red = rgb[23-: 8]; // bits 23 à 16
assign green = rgb[15-: 8]; // bits 15 à 8
assign blue = rgb[7-: 8]; // bits 7 à 0
// Instanciation du contrôleur WS2812B
ws2812b_controller #(.NB_LEDS(NB_LEDS)) ws2812b_controller_inst (
.clk(CLOCK_50),
.data_ws2812b(GPIO_WS2812B),
.*
);
integer i, c;
logic [23:0] led[0:NB_LEDS-1]; // État des LEDs
logic [3:0] bottom_stack, pointer;
logic [23:0] color[0:5];
initial begin // synthétisable avec Quartus Pro
for (i=0; i<NB_LEDS; i=i+1) led[i] = {OFF, OFF, OFF};
color[0] = {ON, OFF, OFF}; // red
color[1] = {OFF, ON, OFF}; // green
color[2] = {OFF, OFF, ON}; // blue
color[3] = {ON, ON, OFF}; // yellow
color[4] = {OFF, ON, ON}; // cyan
color[5] = {ON, OFF, ON}; // purple
bottom_stack = NB_LEDS - 1;
pointer = 0;
end
// assignation des sorties
assign load = (num_led < NB_LEDS);
assign address = load ? num_led : 0;
assign rgb = load ? led[num_led] : 0;
assign latch_n = ~(num_led == NB_LEDS);
// Chargement & animation
always_ff @(posedge CLOCK_50) begin
if (num_led <= NB_LEDS) begin // chargement led par led
num_led <= num_led + 1;
end else if (num_led==NB_LEDS+1) begin
if (delay[21]==1) begin // si fin temporisation
for (i=0; i<=NB_LEDS-1 ; i=i+1) begin
if (i <= bottom_stack) begin
led[i] <= (i == pointer) ? color[c] : {OFF, OFF, OFF};
end else begin
led[i] <= color[c];
end
end
pointer <= pointer + 1;
if (pointer == bottom_stack) begin
pointer <= 0;
bottom_stack <= bottom_stack - 1;
if (bottom_stack == 1) begin
bottom_stack <= NB_LEDS - 1;
c <= c + 1;
if (c==5) c<=0;
end
end
num_led <= 0; // retour à l'état initial
delay <= 0;
end else begin
delay <= delay + 1;
end
end
end
endmodule
Feu…
Ouais, je sais… Le titre du post est un poil putaclic ;-)
Cet article est sous licence CC BY 4.0 par l'auteur.