1#![no_std]
2use embedded_hal::blocking::delay::DelayUs;
3use embedded_hal::digital::v2::OutputPin;
4pub struct Hub75<PINS> {
22 data: [[(u8, u8, u8, u8, u8, u8); 64]; 16],
24 brightness_step: u8,
25 brightness_count: u8,
26 pins: PINS,
27}
28
29pub trait Outputs {
33 type R1: OutputPin;
34 type G1: OutputPin;
35 type B1: OutputPin;
36 type R2: OutputPin;
37 type G2: OutputPin;
38 type B2: OutputPin;
39 type A: OutputPin;
40 type B: OutputPin;
41 type C: OutputPin;
42 type D: OutputPin;
43 type CLK: OutputPin;
44 type LAT: OutputPin;
45 type OE: OutputPin;
46 fn r1(&mut self) -> &mut Self::R1;
47 fn g1(&mut self) -> &mut Self::G1;
48 fn b1(&mut self) -> &mut Self::B1;
49 fn r2(&mut self) -> &mut Self::R2;
50 fn g2(&mut self) -> &mut Self::G2;
51 fn b2(&mut self) -> &mut Self::B2;
52 fn a(&mut self) -> &mut Self::A;
53 fn b(&mut self) -> &mut Self::B;
54 fn c(&mut self) -> &mut Self::C;
55 fn d(&mut self) -> &mut Self::D;
56 fn clk(&mut self) -> &mut Self::CLK;
57 fn lat(&mut self) -> &mut Self::LAT;
58 fn oe(&mut self) -> &mut Self::OE;
59}
60
61impl<
62 R1: OutputPin,
63 G1: OutputPin,
64 B1: OutputPin,
65 R2: OutputPin,
66 G2: OutputPin,
67 B2: OutputPin,
68 A: OutputPin,
69 B: OutputPin,
70 C: OutputPin,
71 D: OutputPin,
72 CLK: OutputPin,
73 LAT: OutputPin,
74 OE: OutputPin,
75 > Outputs for (R1, G1, B1, R2, G2, B2, A, B, C, D, CLK, LAT, OE)
76{
77 type R1 = R1;
78 type G1 = G1;
79 type B1 = B1;
80 type R2 = R2;
81 type G2 = G2;
82 type B2 = B2;
83 type A = A;
84 type B = B;
85 type C = C;
86 type D = D;
87 type CLK = CLK;
88 type LAT = LAT;
89 type OE = OE;
90 fn r1(&mut self) -> &mut R1 {
91 &mut self.0
92 }
93 fn g1(&mut self) -> &mut G1 {
94 &mut self.1
95 }
96 fn b1(&mut self) -> &mut B1 {
97 &mut self.2
98 }
99 fn r2(&mut self) -> &mut R2 {
100 &mut self.3
101 }
102 fn g2(&mut self) -> &mut G2 {
103 &mut self.4
104 }
105 fn b2(&mut self) -> &mut B2 {
106 &mut self.5
107 }
108 fn a(&mut self) -> &mut A {
109 &mut self.6
110 }
111 fn b(&mut self) -> &mut B {
112 &mut self.7
113 }
114 fn c(&mut self) -> &mut C {
115 &mut self.8
116 }
117 fn d(&mut self) -> &mut D {
118 &mut self.9
119 }
120 fn clk(&mut self) -> &mut CLK {
121 &mut self.10
122 }
123 fn lat(&mut self) -> &mut LAT {
124 &mut self.11
125 }
126 fn oe(&mut self) -> &mut OE {
127 &mut self.12
128 }
129}
130
131impl<PINS: Outputs> Hub75<PINS> {
132 pub fn new(pins: PINS, brightness_bits: u8) -> Self {
144 assert!(brightness_bits < 9 && brightness_bits > 0);
145 let data = [[(0, 0, 0, 0, 0, 0); 64]; 16];
146 let brightness_step = 1 << (8 - brightness_bits);
147 let brightness_count = ((1 << brightness_bits as u16) - 1) as u8;
148 Self {
149 data,
150 brightness_step,
151 brightness_count,
152 pins,
153 }
154 }
155
156 pub fn output<DELAY: DelayUs<u8>>(&mut self, delay: &mut DELAY) {
161 self.pins.oe().set_low().ok();
164 for mut brightness in 0..self.brightness_count {
166 brightness = (brightness + 1).saturating_mul(self.brightness_step);
167 for (count, row) in self.data.iter().enumerate() {
168 for element in row.iter() {
169 if element.0 >= brightness {
170 self.pins.r1().set_high().ok();
171 } else {
172 self.pins.r1().set_low().ok();
173 }
174 if element.1 >= brightness {
175 self.pins.g1().set_high().ok();
176 } else {
177 self.pins.g1().set_low().ok();
178 }
179 if element.2 >= brightness {
180 self.pins.b1().set_high().ok();
181 } else {
182 self.pins.b1().set_low().ok();
183 }
184 if element.3 >= brightness {
185 self.pins.r2().set_high().ok();
186 } else {
187 self.pins.r2().set_low().ok();
188 }
189 if element.4 >= brightness {
190 self.pins.g2().set_high().ok();
191 } else {
192 self.pins.g2().set_low().ok();
193 }
194 if element.5 >= brightness {
195 self.pins.b2().set_high().ok();
196 } else {
197 self.pins.b2().set_low().ok();
198 }
199 self.pins.clk().set_high().ok();
200 self.pins.clk().set_low().ok();
201 }
202 self.pins.oe().set_high().ok();
203 delay.delay_us(2);
205 self.pins.lat().set_low().ok();
206 delay.delay_us(2);
207 self.pins.lat().set_high().ok();
208 if count & 1 != 0 {
210 self.pins.a().set_high().ok();
211 } else {
212 self.pins.a().set_low().ok();
213 }
214 if count & 2 != 0 {
215 self.pins.b().set_high().ok();
216 } else {
217 self.pins.b().set_low().ok();
218 }
219 if count & 4 != 0 {
220 self.pins.c().set_high().ok();
221 } else {
222 self.pins.c().set_low().ok();
223 }
224 if count & 8 != 0 {
225 self.pins.d().set_high().ok();
226 } else {
227 self.pins.d().set_low().ok();
228 }
229 delay.delay_us(2);
230 self.pins.oe().set_low().ok();
231 }
232 }
233 self.pins.oe().set_high().ok();
236 }
237 pub fn clear(&mut self) {
242 for row in self.data.iter_mut() {
243 for e in row.iter_mut() {
244 e.0 = 0;
245 e.1 = 0;
246 e.2 = 0;
247 e.3 = 0;
248 e.4 = 0;
249 e.5 = 0;
250 }
251 }
252 }
253}
254
255use embedded_graphics::{
256 drawable::{Dimensions, Pixel},
257 pixelcolor::Rgb565,
258 Drawing, SizedDrawing,
259};
260impl<PINS: Outputs> Drawing<Rgb565> for Hub75<PINS> {
261 fn draw<T>(&mut self, item_pixels: T)
262 where
263 T: IntoIterator<Item = Pixel<Rgb565>>,
264 {
265 const GAMMA8: [u8; 256] = [
271 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
272 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4,
273 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11,
274 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22,
275 22, 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37,
276 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 54, 55, 56, 57, 58,
277 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85,
278 86, 87, 89, 90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114,
279 115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142, 144,
280 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175, 177, 180,
281 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213, 215, 218, 220,
282 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255,
283 ];
284 for Pixel(coord, color) in item_pixels {
285 let row = coord[1] % 16;
286 let data = &mut self.data[row as usize][coord[0] as usize];
287 if coord[1] >= 16 {
288 data.3 = GAMMA8[color.r() as usize];
289 data.4 = GAMMA8[color.g() as usize];
290 data.5 = GAMMA8[color.b() as usize];
291 } else {
292 data.0 = GAMMA8[color.r() as usize];
293 data.1 = GAMMA8[color.g() as usize];
294 data.2 = GAMMA8[color.b() as usize];
295 }
296 }
297 }
298}
299
300impl<PINS: Outputs> SizedDrawing<Rgb565> for Hub75<PINS> {
302 fn draw_sized<T>(&mut self, item_pixels: T)
303 where
304 T: IntoIterator<Item = Pixel<Rgb565>> + Dimensions,
305 {
306 self.draw(item_pixels);
307 }
308}