#[cfg(feature = "fake-hardware")]
extern crate ansi_term;
extern crate failure;
extern crate rgb;
#[cfg(feature = "hardware")]
extern crate spidev;
#[cfg(feature = "fake-hardware")]
use ansi_term::Color::RGB;
#[cfg(feature = "fake-hardware")]
use ansi_term::ANSIStrings;
use failure::Error;
#[cfg(feature = "hardware")]
use rgb::ComponentSlice;
#[cfg(feature = "hardware")]
use std::io::prelude::*;
#[cfg(feature = "hardware")]
use spidev::{SPI_MODE_0, Spidev, SpidevOptions};
const BLACK: rgb::RGB8 = rgb::RGB8 { r: 0, g: 0, b: 0 };
pub enum Rotate {
RotNone,
RotCW90,
RotCCW90,
Rot180,
}
#[cfg(feature = "hardware")]
pub struct UnicornHatHd {
leds: [rgb::RGB8; 256],
spi: Spidev,
rotation: Rotate,
}
#[cfg(feature = "fake-hardware")]
pub struct UnicornHatHd {
leds: [rgb::RGB8; 256],
rotation: Rotate,
}
impl UnicornHatHd {
#[cfg(feature = "hardware")]
pub fn new(spi_path: &str) -> Result<UnicornHatHd, Error> {
let mut spidev = try!(Spidev::open(spi_path));
let options = SpidevOptions::new()
.bits_per_word(8)
.max_speed_hz(9_000_000)
.mode(SPI_MODE_0)
.build();
try!(spidev.configure(&options));
Ok(UnicornHatHd {
leds: [BLACK; 256],
spi: spidev,
rotation: Rotate::RotNone,
})
}
#[cfg(feature = "fake-hardware")]
pub fn new(_spi_path: &str) -> Result<UnicornHatHd, Error> {
Ok(UnicornHatHd {
leds: [BLACK; 256],
rotation: Rotate::RotNone,
})
}
pub fn set_rotation(&mut self, rot: Rotate) {
self.rotation = rot;
}
#[cfg(feature = "hardware")]
pub fn display(&mut self) -> Result<(), Error> {
self.spi.write(&[0x72])?;
let data = self.as_array();
self.spi.write(&data)?;
Ok(())
}
#[cfg(feature = "fake-hardware")]
pub fn display(&mut self) -> Result<(), Error> {
println!("Unicorn HAT HD:");
for y in 0..16 {
let mut line = vec![];
for x in 0..16 {
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: usize, y: usize, c: rgb::RGB8) {
self.leds[(y * 16) + x] = c;
}
pub fn get_pixel(&self, x: usize, y: usize) -> rgb::RGB8 {
self.leds[(y * 16) + x]
}
pub fn clear_pixels(&mut self) {
self.leds = [BLACK; 256];
}
#[cfg(feature = "hardware")]
fn as_array(&self) -> Vec<u8> {
let mut arr: Vec<u8> = vec![];
match self.rotation {
Rotate::RotNone => arr.extend_from_slice(self.leds.as_slice()),
Rotate::RotCW90 => for x in 0..16 {
for y in (0..16).rev() {
let led = self.get_pixel(x, y);
arr.extend_from_slice(led.as_slice());
}
},
Rotate::RotCCW90 => for x in (0..16).rev() {
for y in 0..16 {
let led = self.get_pixel(x, y);
arr.extend_from_slice(led.as_slice());
}
},
Rotate::Rot180 => for led in self.leds.iter().rev() {
arr.extend_from_slice(led.as_slice());
},
}
arr
}
}
impl Default for UnicornHatHd {
fn default() -> UnicornHatHd {
UnicornHatHd::new("/dev/spidev0.0").unwrap()
}
}