cleanup & format
This commit is contained in:
135
src/display.rs
135
src/display.rs
@@ -1,20 +1,18 @@
|
||||
use embedded_graphics::{
|
||||
framebuffer::Framebuffer,
|
||||
image::{Image, ImageRaw},
|
||||
mono_font::{MonoTextStyle, ascii::FONT_8X13},
|
||||
pixelcolor::{
|
||||
raw::{BigEndian},
|
||||
},
|
||||
pixelcolor::raw::BigEndian,
|
||||
prelude::*,
|
||||
primitives::{PrimitiveStyle, Rectangle, StyledDrawable},
|
||||
text::Text,
|
||||
image::{Image, ImageRaw},
|
||||
};
|
||||
use image::GrayImage;
|
||||
use image::RgbImage;
|
||||
use image::{GrayImage};
|
||||
|
||||
use embedded_graphics::pixelcolor::BinaryColor;
|
||||
use embedded_graphics::pixelcolor::raw::RawU1;
|
||||
use crate::killinfo::KillInfo;
|
||||
use embedded_graphics::pixelcolor::BinaryColor;
|
||||
use embedded_graphics::pixelcolor::raw::RawU1;
|
||||
|
||||
const WIDTH: usize = 800;
|
||||
const HEIGHT: usize = 480;
|
||||
@@ -28,10 +26,11 @@ pub struct Display {
|
||||
impl Display {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
width : WIDTH,
|
||||
height : HEIGHT,
|
||||
width: WIDTH,
|
||||
height: HEIGHT,
|
||||
buffer:
|
||||
Framebuffer::<BinaryColor, RawU1, BigEndian, WIDTH, HEIGHT, { WIDTH * HEIGHT }>::new(),
|
||||
Framebuffer::<BinaryColor, RawU1, BigEndian, WIDTH, HEIGHT, { WIDTH * HEIGHT }>::new(
|
||||
),
|
||||
}
|
||||
}
|
||||
pub fn clear(&mut self, on: bool) {
|
||||
@@ -42,17 +41,25 @@ impl Display {
|
||||
};
|
||||
|
||||
self.buffer.clear(color).ok();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_rect(&mut self, x: i32, y: i32, w: u32, h: u32, color: u8) {
|
||||
let rect = Rectangle::new(Point::new(x, y), Size::new(w, h));
|
||||
let bw = if color > 127 { BinaryColor::On } else { BinaryColor::Off };
|
||||
let bw = if color > 127 {
|
||||
BinaryColor::On
|
||||
} else {
|
||||
BinaryColor::Off
|
||||
};
|
||||
let style = PrimitiveStyle::with_fill(bw);
|
||||
rect.draw_styled(&style, &mut self.buffer).ok();
|
||||
}
|
||||
|
||||
pub fn draw_text(&mut self, x: i32, y: i32, text: &str, color: u8) {
|
||||
let bw = if color > 127 { BinaryColor::On } else { BinaryColor::Off };
|
||||
let bw = if color > 127 {
|
||||
BinaryColor::On
|
||||
} else {
|
||||
BinaryColor::Off
|
||||
};
|
||||
let style = MonoTextStyle::new(&FONT_8X13, bw);
|
||||
Text::new(text, Point::new(x, y), style)
|
||||
.draw(&mut self.buffer)
|
||||
@@ -66,19 +73,22 @@ impl Display {
|
||||
if let Some(alliance) = &kill.victim.alliance {
|
||||
let bw_vec = rgb_to_bw_dithered(&alliance.logo);
|
||||
let logo_raw = ImageRaw::<BinaryColor>::new(&bw_vec, alliance.logo.width() as u32);
|
||||
Image::new(&logo_raw, Point::new(x, y)).draw(&mut self.buffer).ok();
|
||||
Image::new(&logo_raw, Point::new(x, y))
|
||||
.draw(&mut self.buffer)
|
||||
.ok();
|
||||
}
|
||||
|
||||
// Draw Ship icon (64x64) if present
|
||||
if let Some(ship) = &kill.victim.ship {
|
||||
|
||||
let bw_vec = rgb_to_bw_dithered(&ship.icon);
|
||||
let logo_raw = ImageRaw::<BinaryColor>::new(&bw_vec, ship.icon.width() as u32);
|
||||
Image::new(&logo_raw, Point::new(x + 64 + 4, current_y)).draw(&mut self.buffer).ok();
|
||||
Image::new(&logo_raw, Point::new(x + 64 + 4, current_y))
|
||||
.draw(&mut self.buffer)
|
||||
.ok();
|
||||
}
|
||||
|
||||
let text_x = x + 64 + 64 + 8;
|
||||
let style = MonoTextStyle::new(&FONT_8X13, BinaryColor::Off );
|
||||
let style = MonoTextStyle::new(&FONT_8X13, BinaryColor::Off);
|
||||
current_y += 8;
|
||||
|
||||
// Character name + Alliance short
|
||||
@@ -89,7 +99,6 @@ impl Display {
|
||||
.map(|a| a.short.as_str())
|
||||
.unwrap_or("");
|
||||
|
||||
|
||||
let char_name = kill
|
||||
.victim
|
||||
.character
|
||||
@@ -98,41 +107,57 @@ impl Display {
|
||||
.unwrap_or("");
|
||||
|
||||
let char_line = format!("{} [{}]", char_name, alliance_short);
|
||||
Text::new(&char_line, Point::new(text_x, current_y), style).draw(&mut self.buffer).ok();
|
||||
Text::new(&char_line, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.buffer)
|
||||
.ok();
|
||||
current_y += 16;
|
||||
|
||||
// Ship name + total value
|
||||
let ship_name = kill.victim.ship.as_ref().map(|s| s.name.as_str()).unwrap_or("Unknown");
|
||||
let value_line = format!("{} - {:.2}M ISK", ship_name, kill.total_value / 1_000_000f64);
|
||||
Text::new(&value_line, Point::new(text_x, current_y), style).draw(&mut self.buffer).ok();
|
||||
let ship_name = kill
|
||||
.victim
|
||||
.ship
|
||||
.as_ref()
|
||||
.map(|s| s.name.as_str())
|
||||
.unwrap_or("Unknown");
|
||||
let value_line = format!(
|
||||
"{} - {:.2}M ISK",
|
||||
ship_name,
|
||||
kill.total_value / 1_000_000f64
|
||||
);
|
||||
Text::new(&value_line, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.buffer)
|
||||
.ok();
|
||||
current_y += 16;
|
||||
|
||||
// System name
|
||||
Text::new(&kill.system_name, Point::new(text_x, current_y), style).draw(&mut self.buffer).ok();
|
||||
Text::new(&kill.system_name, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.buffer)
|
||||
.ok();
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn draw_loss_info(&mut self, kill: &KillInfo, x: i32, y: i32) {
|
||||
pub fn draw_loss_info(&mut self, kill: &KillInfo, x: i32, y: i32) {
|
||||
let mut current_y = y;
|
||||
|
||||
// Draw Alliance logo (64x64) if present
|
||||
if let Some(character) = &kill.victim.character {
|
||||
let bw_vec = rgb_to_bw_dithered(&character.portrait);
|
||||
let logo_raw = ImageRaw::<BinaryColor>::new(&bw_vec, character.portrait.width() as u32);
|
||||
Image::new(&logo_raw, Point::new(x, y)).draw(&mut self.buffer).ok();
|
||||
Image::new(&logo_raw, Point::new(x, y))
|
||||
.draw(&mut self.buffer)
|
||||
.ok();
|
||||
}
|
||||
|
||||
// Draw Ship icon (64x64) if present
|
||||
if let Some(ship) = &kill.victim.ship {
|
||||
|
||||
let bw_vec = rgb_to_bw_dithered(&ship.icon);
|
||||
let logo_raw = ImageRaw::<BinaryColor>::new(&bw_vec, ship.icon.width() as u32);
|
||||
Image::new(&logo_raw, Point::new(x + 64 + 4, current_y)).draw(&mut self.buffer).ok();
|
||||
Image::new(&logo_raw, Point::new(x + 64 + 4, current_y))
|
||||
.draw(&mut self.buffer)
|
||||
.ok();
|
||||
}
|
||||
|
||||
let text_x = x + 64 + 64 + 8;
|
||||
let style = MonoTextStyle::new(&FONT_8X13, BinaryColor::Off );
|
||||
let style = MonoTextStyle::new(&FONT_8X13, BinaryColor::Off);
|
||||
current_y += 8;
|
||||
|
||||
// Character name + Alliance short
|
||||
@@ -143,7 +168,6 @@ impl Display {
|
||||
.map(|a| a.short.as_str())
|
||||
.unwrap_or("");
|
||||
|
||||
|
||||
let char_name = kill
|
||||
.victim
|
||||
.character
|
||||
@@ -152,35 +176,48 @@ impl Display {
|
||||
.unwrap_or("");
|
||||
|
||||
let char_line = format!("{} [{}]", char_name, alliance_short);
|
||||
Text::new(&char_line, Point::new(text_x, current_y), style).draw(&mut self.buffer).ok();
|
||||
Text::new(&char_line, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.buffer)
|
||||
.ok();
|
||||
current_y += 16;
|
||||
|
||||
// Ship name + total value
|
||||
let ship_name = kill.victim.ship.as_ref().map(|s| s.name.as_str()).unwrap_or("Unknown");
|
||||
let value_line = format!("{} - {:.2}M ISK", ship_name, kill.total_value / 1_000_000f64);
|
||||
Text::new(&value_line, Point::new(text_x, current_y), style).draw(&mut self.buffer).ok();
|
||||
let ship_name = kill
|
||||
.victim
|
||||
.ship
|
||||
.as_ref()
|
||||
.map(|s| s.name.as_str())
|
||||
.unwrap_or("Unknown");
|
||||
let value_line = format!(
|
||||
"{} - {:.2}M ISK",
|
||||
ship_name,
|
||||
kill.total_value / 1_000_000f64
|
||||
);
|
||||
Text::new(&value_line, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.buffer)
|
||||
.ok();
|
||||
current_y += 16;
|
||||
|
||||
// System name
|
||||
Text::new(&kill.system_name, Point::new(text_x, current_y), style).draw(&mut self.buffer).ok();
|
||||
Text::new(&kill.system_name, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.buffer)
|
||||
.ok();
|
||||
}
|
||||
|
||||
pub fn flush(&self) {
|
||||
let buf = self.buffer.data();
|
||||
let img_data: Vec<u8> = buf
|
||||
.iter()
|
||||
.flat_map(|byte| (0..8).map(move |i| if (byte >> (7 - i)) & 1 == 1 { 255 } else { 0 }))
|
||||
.take(self.width * self.height)
|
||||
.collect();
|
||||
|
||||
pub fn flush(&self) {
|
||||
let buf = self.buffer.data();
|
||||
let img_data: Vec<u8> = buf
|
||||
.iter()
|
||||
.flat_map(|byte| (0..8).map(move |i| if (byte >> (7-i)) & 1 == 1 { 255 } else { 0 }))
|
||||
.take(self.width * self.height)
|
||||
.collect();
|
||||
|
||||
let img = GrayImage::from_raw(self.width as u32, self.height as u32, img_data).unwrap();
|
||||
img.save("output.png").unwrap();
|
||||
println!("Saved framebuffer to {:?}", "output.png");
|
||||
}
|
||||
let img = GrayImage::from_raw(self.width as u32, self.height as u32, img_data).unwrap();
|
||||
img.save("output.png").unwrap();
|
||||
println!("Saved framebuffer to {:?}", "output.png");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn rgb_to_bw_dithered(rgb: &RgbImage) -> Vec<u8> {
|
||||
let w = rgb.width() as usize;
|
||||
let h = rgb.height() as usize;
|
||||
|
||||
174
src/epaper.rs
174
src/epaper.rs
@@ -1,36 +1,42 @@
|
||||
use embedded_graphics::{
|
||||
image::{Image, ImageRaw}, mono_font::{MonoTextStyleBuilder},prelude::*, text::{Baseline, Text, TextStyleBuilder}
|
||||
image::{Image, ImageRaw},
|
||||
mono_font::MonoTextStyleBuilder,
|
||||
prelude::*,
|
||||
text::{Baseline, Text, TextStyleBuilder},
|
||||
};
|
||||
|
||||
use crate::epd7in5_v2::Epd7in5;
|
||||
use crate::epd7in5_v2::Display7in5;
|
||||
use crate::graphics::Display;
|
||||
use crate::epd::color::Color;
|
||||
use crate::epd::epd7in5_v2::Display7in5;
|
||||
use crate::epd::epd7in5_v2::Epd7in5;
|
||||
use crate::epd::graphics::Display;
|
||||
use crate::epd::traits::*;
|
||||
|
||||
use linux_embedded_hal::{
|
||||
spidev::{self, SpidevOptions}, Delay, SPIError, SpidevDevice
|
||||
Delay, SPIError, SpidevDevice,
|
||||
spidev::{self, SpidevOptions},
|
||||
};
|
||||
|
||||
use crate::traits::{*};
|
||||
use crate::color::Color;
|
||||
use embedded_hal::digital::OutputPin;
|
||||
use embedded_hal::digital::PinState;
|
||||
|
||||
|
||||
use crate::killinfo::KillInfo;
|
||||
use image::RgbImage;
|
||||
|
||||
|
||||
pub struct EPaper {
|
||||
spi : SpidevDevice,
|
||||
epd: Epd7in5<SpidevDevice, gpiocdev_embedded_hal::InputPin, gpiocdev_embedded_hal::OutputPin, gpiocdev_embedded_hal::OutputPin, Delay>,
|
||||
display: Display<800, 480, false, 48000 , Color>,
|
||||
delay :Delay,
|
||||
spi: SpidevDevice,
|
||||
epd: Epd7in5<
|
||||
SpidevDevice,
|
||||
gpiocdev_embedded_hal::InputPin,
|
||||
gpiocdev_embedded_hal::OutputPin,
|
||||
gpiocdev_embedded_hal::OutputPin,
|
||||
Delay,
|
||||
>,
|
||||
display: Display<800, 480, false, 48000, Color>,
|
||||
delay: Delay,
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl EPaper {
|
||||
pub fn new() -> Result<EPaper, SPIError> {
|
||||
|
||||
pub fn new() -> Result<EPaper, SPIError> {
|
||||
let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory");
|
||||
let options = SpidevOptions::new()
|
||||
.bits_per_word(8)
|
||||
@@ -40,11 +46,14 @@ impl EPaper {
|
||||
spi.configure(&options).expect("spi configuration");
|
||||
|
||||
// setup display pins
|
||||
let mut cs = gpiocdev_embedded_hal::OutputPin::new("/dev/gpiochip0", 26, PinState::High).unwrap();
|
||||
let mut cs =
|
||||
gpiocdev_embedded_hal::OutputPin::new("/dev/gpiochip0", 26, PinState::High).unwrap();
|
||||
cs.set_high().unwrap();
|
||||
let busy = gpiocdev_embedded_hal::InputPin::new("/dev/gpiochip0", 24).unwrap();
|
||||
let dc = gpiocdev_embedded_hal::OutputPin::new("/dev/gpiochip0", 25, PinState::High).unwrap();
|
||||
let rst = gpiocdev_embedded_hal::OutputPin::new("/dev/gpiochip0", 17, PinState::High).unwrap();
|
||||
let busy = gpiocdev_embedded_hal::InputPin::new("/dev/gpiochip0", 24).unwrap();
|
||||
let dc =
|
||||
gpiocdev_embedded_hal::OutputPin::new("/dev/gpiochip0", 25, PinState::High).unwrap();
|
||||
let rst =
|
||||
gpiocdev_embedded_hal::OutputPin::new("/dev/gpiochip0", 17, PinState::High).unwrap();
|
||||
|
||||
let mut delay = Delay {};
|
||||
println!("START");
|
||||
@@ -52,47 +61,44 @@ impl EPaper {
|
||||
let display = Display7in5::default();
|
||||
println!("Device successfully initialized!");
|
||||
|
||||
return Ok(EPaper { spi, epd: epd7in5, display, delay : Delay {}});
|
||||
|
||||
return Ok(EPaper {
|
||||
spi,
|
||||
epd: epd7in5,
|
||||
display,
|
||||
delay: Delay {},
|
||||
});
|
||||
}
|
||||
|
||||
pub fn flush(&mut self) -> Result<(), SPIError> {
|
||||
self.epd.update_and_display_frame(&mut self.spi, self.display.buffer(), &mut self.delay)?;
|
||||
pub fn flush(&mut self) -> Result<(), SPIError> {
|
||||
self.epd
|
||||
.update_and_display_frame(&mut self.spi, self.display.buffer(), &mut self.delay)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn sleep(&mut self) -> Result<(), SPIError> {
|
||||
pub fn sleep(&mut self) -> Result<(), SPIError> {
|
||||
self.epd.sleep(&mut self.spi, &mut self.delay)?;
|
||||
Ok(())
|
||||
|
||||
}
|
||||
|
||||
pub fn clear(&mut self, on: bool) {
|
||||
let color = if on {
|
||||
Color::Black
|
||||
} else {
|
||||
Color::White
|
||||
};
|
||||
pub fn clear(&mut self, on: bool) {
|
||||
let color = if on { Color::Black } else { Color::White };
|
||||
|
||||
self.display.clear(color).ok();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_text(&mut self, x: i32, y: i32, text: &str) {
|
||||
let style = MonoTextStyleBuilder::new()
|
||||
.font(&embedded_graphics::mono_font::ascii::FONT_8X13)
|
||||
.text_color(Color::White)
|
||||
.background_color(Color::Black)
|
||||
.build();
|
||||
.font(&embedded_graphics::mono_font::ascii::FONT_8X13)
|
||||
.text_color(Color::White)
|
||||
.background_color(Color::Black)
|
||||
.build();
|
||||
|
||||
let text_style = TextStyleBuilder::new().baseline(Baseline::Top).build();
|
||||
|
||||
let _ = Text::with_text_style(text, Point::new(x, y), style, text_style).draw(&mut self.display);
|
||||
|
||||
let _ = Text::with_text_style(text, Point::new(x, y), style, text_style)
|
||||
.draw(&mut self.display);
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn draw_kill_info(&mut self, kill: &KillInfo, x: i32, y: i32) {
|
||||
let mut current_y = y;
|
||||
|
||||
@@ -100,16 +106,19 @@ impl EPaper {
|
||||
if let Some(alliance) = &kill.victim.alliance {
|
||||
let bw_vec = rgb_to_bw_dithered(&alliance.logo);
|
||||
let logo_raw = ImageRaw::<Color>::new(bw_vec.as_slice(), alliance.logo.width() as u32);
|
||||
Image::new(&logo_raw, Point::new(x, y)).draw(&mut self.display).ok();
|
||||
Image::new(&logo_raw, Point::new(x, y))
|
||||
.draw(&mut self.display)
|
||||
.ok();
|
||||
}
|
||||
|
||||
// Draw Ship icon (64x64) if present
|
||||
if let Some(ship) = &kill.victim.ship {
|
||||
|
||||
let bw_vec = rgb_to_bw_dithered(&ship.icon);
|
||||
let width = ship.icon.width() as u32;
|
||||
let raw_image: ImageRaw<'_, Color> = ImageRaw::<Color>::new(&bw_vec, width);
|
||||
Image::new(&raw_image, Point::new(x + 64 + 4, current_y)).draw(&mut self.display).ok();
|
||||
let width = ship.icon.width() as u32;
|
||||
let raw_image: ImageRaw<'_, Color> = ImageRaw::<Color>::new(&bw_vec, width);
|
||||
Image::new(&raw_image, Point::new(x + 64 + 4, current_y))
|
||||
.draw(&mut self.display)
|
||||
.ok();
|
||||
}
|
||||
|
||||
let text_x = x + 64 + 64 + 8;
|
||||
@@ -129,7 +138,6 @@ impl EPaper {
|
||||
.map(|a| a.short.as_str())
|
||||
.unwrap_or("");
|
||||
|
||||
|
||||
let char_name = kill
|
||||
.victim
|
||||
.character
|
||||
@@ -138,37 +146,53 @@ impl EPaper {
|
||||
.unwrap_or("");
|
||||
|
||||
let char_line = format!("{} [{}]", char_name, alliance_short);
|
||||
Text::new(&char_line, Point::new(text_x, current_y), style).draw(&mut self.display).ok();
|
||||
Text::new(&char_line, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.display)
|
||||
.ok();
|
||||
current_y += 16;
|
||||
|
||||
// Ship name + total value
|
||||
let ship_name = kill.victim.ship.as_ref().map(|s| s.name.as_str()).unwrap_or("Unknown");
|
||||
let value_line = format!("{} - {:.2}M ISK", ship_name, kill.total_value / 1_000_000f64);
|
||||
Text::new(&value_line, Point::new(text_x, current_y), style).draw(&mut self.display).ok();
|
||||
let ship_name = kill
|
||||
.victim
|
||||
.ship
|
||||
.as_ref()
|
||||
.map(|s| s.name.as_str())
|
||||
.unwrap_or("Unknown");
|
||||
let value_line = format!(
|
||||
"{} - {:.2}M ISK",
|
||||
ship_name,
|
||||
kill.total_value / 1_000_000f64
|
||||
);
|
||||
Text::new(&value_line, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.display)
|
||||
.ok();
|
||||
current_y += 16;
|
||||
|
||||
// System name
|
||||
Text::new(&kill.system_name, Point::new(text_x, current_y), style).draw(&mut self.display).ok();
|
||||
Text::new(&kill.system_name, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.display)
|
||||
.ok();
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn draw_loss_info(&mut self, kill: &KillInfo, x: i32, y: i32) {
|
||||
pub fn draw_loss_info(&mut self, kill: &KillInfo, x: i32, y: i32) {
|
||||
let mut current_y = y;
|
||||
|
||||
// Draw Alliance logo (64x64) if present
|
||||
if let Some(character) = &kill.victim.character {
|
||||
let bw_vec = rgb_to_bw_dithered(&character.portrait);
|
||||
let logo_raw = ImageRaw::<Color>::new(&bw_vec, character.portrait.width() as u32);
|
||||
Image::new(&logo_raw, Point::new(x, y)).draw(&mut self.display).ok();
|
||||
Image::new(&logo_raw, Point::new(x, y))
|
||||
.draw(&mut self.display)
|
||||
.ok();
|
||||
}
|
||||
|
||||
// Draw Ship icon (64x64) if present
|
||||
if let Some(ship) = &kill.victim.ship {
|
||||
|
||||
let bw_vec = rgb_to_bw_dithered(&ship.icon);
|
||||
let logo_raw = ImageRaw::<Color>::new(&bw_vec, ship.icon.width() as u32);
|
||||
Image::new(&logo_raw, Point::new(x + 64 + 4, current_y)).draw(&mut self.display).ok();
|
||||
Image::new(&logo_raw, Point::new(x + 64 + 4, current_y))
|
||||
.draw(&mut self.display)
|
||||
.ok();
|
||||
}
|
||||
|
||||
let text_x = x + 64 + 64 + 8;
|
||||
@@ -187,7 +211,6 @@ impl EPaper {
|
||||
.map(|a| a.short.as_str())
|
||||
.unwrap_or("");
|
||||
|
||||
|
||||
let char_name = kill
|
||||
.victim
|
||||
.character
|
||||
@@ -196,24 +219,35 @@ impl EPaper {
|
||||
.unwrap_or("");
|
||||
|
||||
let char_line = format!("{} [{}]", char_name, alliance_short);
|
||||
Text::new(&char_line, Point::new(text_x, current_y), style).draw(&mut self.display).ok();
|
||||
Text::new(&char_line, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.display)
|
||||
.ok();
|
||||
current_y += 16;
|
||||
|
||||
// Ship name + total value
|
||||
let ship_name = kill.victim.ship.as_ref().map(|s| s.name.as_str()).unwrap_or("Unknown");
|
||||
let value_line = format!("{} - {:.2}M ISK", ship_name, kill.total_value / 1_000_000f64);
|
||||
Text::new(&value_line, Point::new(text_x, current_y), style).draw(&mut self.display).ok();
|
||||
let ship_name = kill
|
||||
.victim
|
||||
.ship
|
||||
.as_ref()
|
||||
.map(|s| s.name.as_str())
|
||||
.unwrap_or("Unknown");
|
||||
let value_line = format!(
|
||||
"{} - {:.2}M ISK",
|
||||
ship_name,
|
||||
kill.total_value / 1_000_000f64
|
||||
);
|
||||
Text::new(&value_line, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.display)
|
||||
.ok();
|
||||
current_y += 16;
|
||||
|
||||
// System name
|
||||
Text::new(&kill.system_name, Point::new(text_x, current_y), style).draw(&mut self.display).ok();
|
||||
Text::new(&kill.system_name, Point::new(text_x, current_y), style)
|
||||
.draw(&mut self.display)
|
||||
.ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fn rgb_to_bw_dithered(rgb: &RgbImage) -> Vec<u8> {
|
||||
let w = rgb.width() as usize;
|
||||
let h = rgb.height() as usize;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! SPI Commands for the Waveshare 7.5" E-Ink Display
|
||||
|
||||
use crate::traits;
|
||||
use crate::epd::traits;
|
||||
|
||||
/// Epd7in5 commands
|
||||
///
|
||||
@@ -143,7 +143,7 @@ impl traits::Command for Command {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::traits::Command as CommandTrait;
|
||||
use crate::epd::traits::Command as CommandTrait;
|
||||
|
||||
#[test]
|
||||
fn command_addr() {
|
||||
@@ -16,9 +16,9 @@ use embedded_hal::{
|
||||
spi::SpiDevice,
|
||||
};
|
||||
|
||||
use crate::color::Color;
|
||||
use crate::interface::DisplayInterface;
|
||||
use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay};
|
||||
use crate::epd::color::Color;
|
||||
use crate::epd::interface::DisplayInterface;
|
||||
use crate::epd::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay};
|
||||
|
||||
pub(crate) mod command;
|
||||
use self::command::Command;
|
||||
@@ -26,7 +26,7 @@ use crate::buffer_len;
|
||||
|
||||
/// Full size buffer for use with the 7in5 v2 EPD
|
||||
#[cfg(feature = "graphics")]
|
||||
pub type Display7in5 = crate::graphics::Display<
|
||||
pub type Display7in5 = crate::epd::graphics::Display<
|
||||
WIDTH,
|
||||
HEIGHT,
|
||||
false,
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Graphics Support for EPDs
|
||||
|
||||
use crate::color::{ColorType, TriColor};
|
||||
use crate::epd::color::{ColorType, TriColor};
|
||||
use core::marker::PhantomData;
|
||||
use embedded_graphics::prelude::*;
|
||||
|
||||
@@ -59,12 +59,12 @@ pub struct Display<
|
||||
}
|
||||
|
||||
impl<
|
||||
const WIDTH: u32,
|
||||
const HEIGHT: u32,
|
||||
const BWRBIT: bool,
|
||||
const BYTECOUNT: usize,
|
||||
COLOR: ColorType + PixelColor,
|
||||
> Default for Display<WIDTH, HEIGHT, BWRBIT, BYTECOUNT, COLOR>
|
||||
const WIDTH: u32,
|
||||
const HEIGHT: u32,
|
||||
const BWRBIT: bool,
|
||||
const BYTECOUNT: usize,
|
||||
COLOR: ColorType + PixelColor,
|
||||
> Default for Display<WIDTH, HEIGHT, BWRBIT, BYTECOUNT, COLOR>
|
||||
{
|
||||
/// Initialize display with the color '0', which may not be the same on all device.
|
||||
/// Many devices have a bit parameter polarity that should be changed if this is not the right
|
||||
@@ -87,12 +87,12 @@ impl<
|
||||
|
||||
/// For use with embedded_grahics
|
||||
impl<
|
||||
const WIDTH: u32,
|
||||
const HEIGHT: u32,
|
||||
const BWRBIT: bool,
|
||||
const BYTECOUNT: usize,
|
||||
COLOR: ColorType + PixelColor,
|
||||
> DrawTarget for Display<WIDTH, HEIGHT, BWRBIT, BYTECOUNT, COLOR>
|
||||
const WIDTH: u32,
|
||||
const HEIGHT: u32,
|
||||
const BWRBIT: bool,
|
||||
const BYTECOUNT: usize,
|
||||
COLOR: ColorType + PixelColor,
|
||||
> DrawTarget for Display<WIDTH, HEIGHT, BWRBIT, BYTECOUNT, COLOR>
|
||||
{
|
||||
type Color = COLOR;
|
||||
type Error = core::convert::Infallible;
|
||||
@@ -110,12 +110,12 @@ impl<
|
||||
|
||||
/// For use with embedded_grahics
|
||||
impl<
|
||||
const WIDTH: u32,
|
||||
const HEIGHT: u32,
|
||||
const BWRBIT: bool,
|
||||
const BYTECOUNT: usize,
|
||||
COLOR: ColorType + PixelColor,
|
||||
> OriginDimensions for Display<WIDTH, HEIGHT, BWRBIT, BYTECOUNT, COLOR>
|
||||
const WIDTH: u32,
|
||||
const HEIGHT: u32,
|
||||
const BWRBIT: bool,
|
||||
const BYTECOUNT: usize,
|
||||
COLOR: ColorType + PixelColor,
|
||||
> OriginDimensions for Display<WIDTH, HEIGHT, BWRBIT, BYTECOUNT, COLOR>
|
||||
{
|
||||
fn size(&self) -> Size {
|
||||
match self.rotation {
|
||||
@@ -126,12 +126,12 @@ impl<
|
||||
}
|
||||
|
||||
impl<
|
||||
const WIDTH: u32,
|
||||
const HEIGHT: u32,
|
||||
const BWRBIT: bool,
|
||||
const BYTECOUNT: usize,
|
||||
COLOR: ColorType + PixelColor,
|
||||
> Display<WIDTH, HEIGHT, BWRBIT, BYTECOUNT, COLOR>
|
||||
const WIDTH: u32,
|
||||
const HEIGHT: u32,
|
||||
const BWRBIT: bool,
|
||||
const BYTECOUNT: usize,
|
||||
COLOR: ColorType + PixelColor,
|
||||
> Display<WIDTH, HEIGHT, BWRBIT, BYTECOUNT, COLOR>
|
||||
{
|
||||
/// get internal buffer to use it (to draw in epd)
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
@@ -354,10 +354,8 @@ fn set_pixel<COLOR: ColorType + PixelColor>(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::color::*;
|
||||
use embedded_graphics::{
|
||||
primitives::{Line, PrimitiveStyle},
|
||||
};
|
||||
use crate::epd::color::*;
|
||||
use embedded_graphics::primitives::{Line, PrimitiveStyle};
|
||||
|
||||
// test buffer length
|
||||
#[test]
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::traits::Command;
|
||||
use crate::epd::traits::Command;
|
||||
use core::marker::PhantomData;
|
||||
use embedded_hal::{delay::*, digital::*, spi::SpiDevice};
|
||||
|
||||
12
src/epd/mod.rs
Normal file
12
src/epd/mod.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
pub mod graphics;
|
||||
|
||||
pub mod traits;
|
||||
|
||||
pub mod color;
|
||||
|
||||
pub mod rect;
|
||||
|
||||
/// Interface for the physical connection between display and the controlling device
|
||||
pub mod interface;
|
||||
|
||||
pub mod epd7in5_v2;
|
||||
@@ -111,9 +111,8 @@ impl Individual {
|
||||
alli_id: u32,
|
||||
ship_id: u32,
|
||||
) -> Result<Individual, EsiError> {
|
||||
|
||||
let character = if char_id != 0 {
|
||||
client.get_character(char_id).ok()
|
||||
client.get_character(char_id).ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
95
src/lib.rs
95
src/lib.rs
@@ -1,101 +1,8 @@
|
||||
//! A simple Driver for the [Waveshare](https://github.com/waveshare/e-Paper) E-Ink Displays via SPI
|
||||
//!
|
||||
//! - Built using [`embedded-hal`] traits.
|
||||
//! - Graphics support is added through [`embedded-graphics`]
|
||||
//!
|
||||
//! [`embedded-graphics`]: https://docs.rs/embedded-graphics/
|
||||
//! [`embedded-hal`]: https://docs.rs/embedded-hal
|
||||
//!
|
||||
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//!```rust, no_run
|
||||
//!# use embedded_hal_mock::eh1::*;
|
||||
//!# fn main() -> Result<(), embedded_hal::spi::ErrorKind> {
|
||||
//!use embedded_graphics::{
|
||||
//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle},
|
||||
//!};
|
||||
//!use epd_waveshare::{epd1in54::*, prelude::*};
|
||||
//!#
|
||||
//!# let expectations = [];
|
||||
//!# let mut spi = spi::Mock::new(&expectations);
|
||||
//!# let expectations = [];
|
||||
//!# let cs_pin = digital::Mock::new(&expectations);
|
||||
//!# let busy_in = digital::Mock::new(&expectations);
|
||||
//!# let dc = digital::Mock::new(&expectations);
|
||||
//!# let rst = digital::Mock::new(&expectations);
|
||||
//!# let mut delay = delay::NoopDelay::new();
|
||||
//!
|
||||
//!// Setup EPD
|
||||
//!let mut epd = Epd1in54::new(&mut spi, busy_in, dc, rst, &mut delay, None)?;
|
||||
//!
|
||||
//!// Use display graphics from embedded-graphics
|
||||
//!let mut display = Display1in54::default();
|
||||
//!
|
||||
//!// Use embedded graphics for drawing a line
|
||||
//!
|
||||
//!let _ = Line::new(Point::new(0, 120), Point::new(0, 295))
|
||||
//! .into_styled(PrimitiveStyle::with_stroke(Color::Black, 1))
|
||||
//! .draw(&mut display);
|
||||
//!
|
||||
//! // Display updated frame
|
||||
//!epd.update_frame(&mut spi, &display.buffer(), &mut delay)?;
|
||||
//!epd.display_frame(&mut spi, &mut delay)?;
|
||||
//!
|
||||
//!// Set the EPD to sleep
|
||||
//!epd.sleep(&mut spi, &mut delay)?;
|
||||
//!# Ok(())
|
||||
//!# }
|
||||
//!```
|
||||
//!
|
||||
//! # Other information and requirements
|
||||
//!
|
||||
//! - Buffersize: Wherever a buffer is used it always needs to be of the size: `width / 8 * length`,
|
||||
//! where width and length being either the full e-ink size or the partial update window size
|
||||
//!
|
||||
//! ### SPI
|
||||
//!
|
||||
//! MISO is not connected/available. SPI_MODE_0 is used (CPHL = 0, CPOL = 0) with 8 bits per word, MSB first.
|
||||
//!
|
||||
//! Maximum speed tested by myself was 8Mhz but more should be possible (Ben Krasnow used 18Mhz with his implemenation)
|
||||
//!
|
||||
|
||||
#[cfg(feature = "graphics")]
|
||||
pub mod graphics;
|
||||
|
||||
pub mod traits;
|
||||
|
||||
pub mod color;
|
||||
|
||||
pub mod rect;
|
||||
|
||||
/// Interface for the physical connection between display and the controlling device
|
||||
pub mod interface;
|
||||
|
||||
pub mod epd7in5_v2;
|
||||
|
||||
|
||||
pub mod epd;
|
||||
pub mod killinfo;
|
||||
pub mod model;
|
||||
pub mod services;
|
||||
|
||||
|
||||
pub mod type_a;
|
||||
|
||||
/// Includes everything important besides the chosen Display
|
||||
pub mod prelude {
|
||||
pub use crate::color::{Color, OctColor, TriColor};
|
||||
pub use crate::traits::{
|
||||
QuickRefresh, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay,
|
||||
};
|
||||
|
||||
pub use crate::SPI_MODE;
|
||||
|
||||
#[cfg(feature = "graphics")]
|
||||
pub use crate::graphics::{Display, DisplayRotation};
|
||||
}
|
||||
|
||||
/// Computes the needed buffer length. Takes care of rounding up in case width
|
||||
/// is not divisible by 8.
|
||||
///
|
||||
|
||||
38
src/main.rs
38
src/main.rs
@@ -1,52 +1,32 @@
|
||||
pub mod graphics;
|
||||
|
||||
pub mod traits;
|
||||
|
||||
pub mod color;
|
||||
|
||||
pub mod rect;
|
||||
|
||||
/// Interface for the physical connection between display and the controlling device
|
||||
pub mod interface;
|
||||
|
||||
pub mod epd7in5_v2;
|
||||
|
||||
pub mod display;
|
||||
pub mod epaper;
|
||||
pub mod epd;
|
||||
pub mod killinfo;
|
||||
pub mod model;
|
||||
pub mod services;
|
||||
pub mod epaper;
|
||||
|
||||
pub mod type_a;
|
||||
use crate::killinfo::KillInfo;
|
||||
use crate::services::esi_static::EsiClient;
|
||||
use crate::services::zkill::ZkillClient;
|
||||
|
||||
|
||||
pub const fn buffer_len(width: usize, height: usize) -> usize {
|
||||
(width + 7) / 8 * height
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fn main() {
|
||||
|
||||
|
||||
let esi = EsiClient::new();
|
||||
let zkill = ZkillClient::new();
|
||||
|
||||
let past_seconds = 60 * 60 * 24;
|
||||
let my_corp_id = 98685373;
|
||||
|
||||
let mut display = display::Display::new();
|
||||
let mut display = display::Display::new();
|
||||
let mut epaper = epaper::EPaper::new().expect("DisplayError");
|
||||
|
||||
display.clear(true);
|
||||
epaper.clear(true);
|
||||
epaper.flush().expect("flush error");
|
||||
|
||||
|
||||
let response = zkill
|
||||
.get_corporation_kills(my_corp_id, past_seconds)
|
||||
.unwrap();
|
||||
@@ -58,11 +38,9 @@ fn main() {
|
||||
.map(|r| builder.make_kill_info(&zkill, &esi, r).unwrap())
|
||||
.collect();
|
||||
|
||||
|
||||
|
||||
for (i,k) in killmails.iter().enumerate() {
|
||||
for (i, k) in killmails.iter().enumerate() {
|
||||
let ii = i as i32;
|
||||
let y : i32 = ii * 60;
|
||||
let y: i32 = ii * 60;
|
||||
|
||||
display.draw_kill_info(k, 0, y);
|
||||
epaper.draw_kill_info(k, 0, y);
|
||||
@@ -79,9 +57,9 @@ fn main() {
|
||||
.map(|r| builder.make_kill_info(&zkill, &esi, r).unwrap())
|
||||
.collect();
|
||||
|
||||
for (i,k) in killmails.iter().enumerate() {
|
||||
for (i, k) in killmails.iter().enumerate() {
|
||||
let ii = i as i32;
|
||||
let y : i32 = ii * 60;
|
||||
let y: i32 = ii * 60;
|
||||
|
||||
display.draw_loss_info(k, 400, y);
|
||||
epaper.draw_loss_info(k, 400, y);
|
||||
@@ -89,6 +67,4 @@ fn main() {
|
||||
|
||||
display.flush();
|
||||
epaper.flush().expect("flush error");
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
//! SPI Commands for the Waveshare 2.9" and 1.54" E-Ink Display
|
||||
|
||||
use crate::traits;
|
||||
|
||||
/// Epd1in54 and EPD2IN9 commands
|
||||
///
|
||||
/// Should rarely (never?) be needed directly.
|
||||
///
|
||||
/// For more infos about the addresses and what they are doing look into the pdfs
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) enum Command {
|
||||
/// Driver Output control
|
||||
/// 3 Databytes:
|
||||
/// A[7:0]
|
||||
/// 0.. A[8]
|
||||
/// 0.. B[2:0]
|
||||
/// Default: Set A[8:0] = 0x127 and B[2:0] = 0x0
|
||||
DriverOutputControl = 0x01,
|
||||
GateDrivingVoltage = 0x03,
|
||||
SourceDrivingVoltage = 0x04,
|
||||
/// Booster Soft start control
|
||||
/// 3 Databytes:
|
||||
/// 1.. A[6:0]
|
||||
/// 1.. B[6:0]
|
||||
/// 1.. C[6:0]
|
||||
/// Default: A[7:0] = 0xCF, B[7:0] = 0xCE, C[7:0] = 0x8D
|
||||
BoosterSoftStartControl = 0x0C,
|
||||
GateScanStartPosition = 0x0F,
|
||||
//TODO: useful?
|
||||
// GateScanStartPosition = 0x0F,
|
||||
/// Deep Sleep Mode Control
|
||||
/// 1 Databyte:
|
||||
/// 0.. A[0]
|
||||
/// Values:
|
||||
/// A[0] = 0: Normal Mode (POR)
|
||||
/// A[0] = 1: Enter Deep Sleep Mode
|
||||
DeepSleepMode = 0x10,
|
||||
// /// Data Entry mode setting
|
||||
DataEntryModeSetting = 0x11,
|
||||
|
||||
SwReset = 0x12,
|
||||
|
||||
TemperatureSensorSelection = 0x18,
|
||||
|
||||
TemperatureSensorControl = 0x1A,
|
||||
|
||||
MasterActivation = 0x20,
|
||||
|
||||
DisplayUpdateControl1 = 0x21,
|
||||
|
||||
DisplayUpdateControl2 = 0x22,
|
||||
|
||||
WriteRam = 0x24,
|
||||
|
||||
WriteRam2 = 0x26,
|
||||
|
||||
WriteVcomRegister = 0x2C,
|
||||
|
||||
WriteLutRegister = 0x32,
|
||||
|
||||
WriteOtpSelection = 0x37,
|
||||
|
||||
SetDummyLinePeriod = 0x3A,
|
||||
|
||||
SetGateLineWidth = 0x3B,
|
||||
|
||||
BorderWaveformControl = 0x3C,
|
||||
|
||||
WriteLutRegisterEnd = 0x3f,
|
||||
|
||||
SetRamXAddressStartEndPosition = 0x44,
|
||||
|
||||
SetRamYAddressStartEndPosition = 0x45,
|
||||
|
||||
SetRamXAddressCounter = 0x4E,
|
||||
|
||||
SetRamYAddressCounter = 0x4F,
|
||||
|
||||
Nop = 0xFF,
|
||||
}
|
||||
|
||||
impl traits::Command for Command {
|
||||
/// Returns the address of the command
|
||||
fn address(self) -> u8 {
|
||||
self as u8
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Command;
|
||||
use crate::traits::Command as CommandTrait;
|
||||
|
||||
#[test]
|
||||
fn command_addr() {
|
||||
assert_eq!(Command::DriverOutputControl.address(), 0x01);
|
||||
|
||||
assert_eq!(Command::SetRamXAddressCounter.address(), 0x4E);
|
||||
|
||||
assert_eq!(Command::Nop.address(), 0xFF);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
pub(crate) mod command;
|
||||
pub(crate) mod constants;
|
||||
Reference in New Issue
Block a user