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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#[cfg(feature = "fake-hardware")]
extern crate ansi_term;
extern crate failure;
extern crate rgb;
#[cfg(feature = "hardware")]
extern crate rppal;
#[cfg(feature = "fake-hardware")]
use ansi_term::ANSIStrings;
#[cfg(feature = "fake-hardware")]
use ansi_term::Color::RGB;
use failure::Error;
#[cfg(feature = "hardware")]
use rppal::spi::{Bus, Mode, SlaveSelect, Spi};
const LED_SIZE: usize = 16;
#[cfg(feature = "hardware")]
const BUFFER_SIZE: usize = 256 * 3;
const BLACK: rgb::RGB8 = rgb::RGB8::new(0, 0, 0);
#[cfg(feature = "hardware")]
pub struct UnicornHatHd {
leds: [[rgb::RGB8; LED_SIZE]; LED_SIZE],
spi: Spi,
}
#[cfg(feature = "fake-hardware")]
pub struct UnicornHatHd {
leds: [[rgb::RGB8; LED_SIZE]; LED_SIZE],
}
impl UnicornHatHd {
#[cfg(feature = "hardware")]
pub fn new(bus: Bus, slave_select: SlaveSelect) -> Result<UnicornHatHd, Error> {
let spi = Spi::new(bus, slave_select, 9_000_000, Mode::Mode0)?;
Ok(UnicornHatHd {
leds: [[BLACK; LED_SIZE]; LED_SIZE],
spi,
})
}
#[cfg(feature = "fake-hardware")]
pub fn new(_bus: (), _slave_select: ()) -> Result<UnicornHatHd, Error> {
Ok(UnicornHatHd {
leds: [[BLACK; LED_SIZE]; LED_SIZE],
})
}
#[cfg(feature = "hardware")]
pub fn display(&mut self) -> Result<(), Error> {
self.spi.write(&[0x72])?;
let mut res: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
let mut i = 0;
for rgb in self.leds.iter().flat_map(|r| r.iter()) {
res[i] = rgb.r;
i += 1;
res[i] = rgb.g;
i += 1;
res[i] = rgb.b;
i += 1;
}
self.spi.write(&res)?;
Ok(())
}
#[cfg(feature = "fake-hardware")]
pub fn display(&mut self) -> Result<(), Error> {
println!("Unicorn HAT HD:");
for y in 0..LED_SIZE {
let mut line = vec![];
for x in 0..LED_SIZE {
let pixel = self.get_pixel(x, y);
line.push(RGB(pixel.r, pixel.g, pixel.b).paint("*"));
}
println!("{}", ANSIStrings(&line));
}
Ok(())
}
pub fn set_pixel(&mut self, x_coord: usize, y_coord: usize, c: rgb::RGB8) {
self.leds[y_coord][x_coord] = rgb::RGB8::new(c.r, c.g, c.b)
}
pub fn get_pixel(&self, x_coord: usize, y_coord: usize) -> rgb::RGB8 {
self.leds[y_coord][x_coord]
}
pub fn clear_pixels(&mut self) {
self.leds = [[BLACK; LED_SIZE]; LED_SIZE];
}
}
impl Default for UnicornHatHd {
#[cfg(feature = "hardware")]
fn default() -> UnicornHatHd {
UnicornHatHd::new(Bus::Spi0, SlaveSelect::Ss0).unwrap()
}
#[cfg(feature = "fake-hardware")]
fn default() -> UnicornHatHd {
UnicornHatHd::new((), ()).unwrap()
}
}