From 10c74910af448c5219b9a62742215554441e7403 Mon Sep 17 00:00:00 2001 From: Annika Hannig Date: Fri, 26 Aug 2022 16:54:31 +0200 Subject: [PATCH] initial project --- airportdisplay/.gitignore | 2 + airportdisplay/Cargo.toml | 8 +++ airportdisplay/src/display/commands.rs | 26 +++++++++ airportdisplay/src/display/mod.rs | 6 ++ airportdisplay/src/display/protocol.rs | 79 ++++++++++++++++++++++++++ airportdisplay/src/display/window.rs | 27 +++++++++ airportdisplay/src/lib.rs | 3 + hello_display/.gitignore | 1 + hello_display/Cargo.lock | 30 ++++++++++ hello_display/Cargo.toml | 11 ++++ hello_display/src/main.rs | 16 ++++++ 11 files changed, 209 insertions(+) create mode 100644 airportdisplay/.gitignore create mode 100644 airportdisplay/Cargo.toml create mode 100644 airportdisplay/src/display/commands.rs create mode 100644 airportdisplay/src/display/mod.rs create mode 100644 airportdisplay/src/display/protocol.rs create mode 100644 airportdisplay/src/display/window.rs create mode 100644 airportdisplay/src/lib.rs create mode 100644 hello_display/.gitignore create mode 100644 hello_display/Cargo.lock create mode 100644 hello_display/Cargo.toml create mode 100644 hello_display/src/main.rs diff --git a/airportdisplay/.gitignore b/airportdisplay/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/airportdisplay/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/airportdisplay/Cargo.toml b/airportdisplay/Cargo.toml new file mode 100644 index 0000000..1851b79 --- /dev/null +++ b/airportdisplay/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "airportdisplay" +version = "0.1.0" +edition = "2021" + +[dependencies] +"bytes" = "1.2" + diff --git a/airportdisplay/src/display/commands.rs b/airportdisplay/src/display/commands.rs new file mode 100644 index 0000000..885652f --- /dev/null +++ b/airportdisplay/src/display/commands.rs @@ -0,0 +1,26 @@ +use super::window::Window; + +/// Luminance value +pub struct Luminance(Window, u8); + +/// TextRaw holds bytes and a window +pub struct TextRaw(pub Window, pub Vec); + +/// TextBuffer holds a window an a text buffer +/// the text will be truncated to fit into the window +pub struct TextBuffer(pub Window, pub String); + +/// Text Commands +pub enum Text { + Raw(TextRaw), + Buffer(TextBuffer), +} + +/// Display Commands +pub enum Command { + Reset, + Clear, + Reboot, + Fadeout, + Text(Text), +} diff --git a/airportdisplay/src/display/mod.rs b/airportdisplay/src/display/mod.rs new file mode 100644 index 0000000..ea37921 --- /dev/null +++ b/airportdisplay/src/display/mod.rs @@ -0,0 +1,6 @@ +pub mod commands; +pub mod protocol; +pub mod window; + +pub const TEXT_COLUMNS: usize = 56; +pub const TEXT_ROWS: usize = 20; diff --git a/airportdisplay/src/display/protocol.rs b/airportdisplay/src/display/protocol.rs new file mode 100644 index 0000000..7f7bd79 --- /dev/null +++ b/airportdisplay/src/display/protocol.rs @@ -0,0 +1,79 @@ +use std::convert::From; + +use bytes::BufMut; + +use super::{ + commands::{Command, Text, TextBuffer, TextRaw}, + window::Window, + TEXT_COLUMNS, TEXT_ROWS, +}; + +/// A frame holds a single encoded display command, +/// like set text at pos x, y. +type Frame = Vec; + +/// Data is a list of commands to be sent to the display. +type Data = Vec; + +/// Encode window data +impl From for Frame { + fn from(Window { x, y, w, h }: Window) -> Self { + let mut buf = vec![]; + buf.put_u16_le(x); + buf.put_u16_le(y); + buf.put_u16_le(w); + buf.put_u16_le(h); + buf + } +} + +impl From for Data { + fn from(TextRaw(window, bytes): TextRaw) -> Data { + let mut bytes = bytes.clone(); + bytes.truncate(TEXT_COLUMNS); + vec![[vec![0x03, 0x00], window.into(), bytes].concat()] + } +} + +impl From for Data { + fn from(TextBuffer(window, text): TextBuffer) -> Data { + // let Window { x, y, w, h } = window; + let mut lines: Vec<&str> = text.split("\n").collect(); + lines.truncate(TEXT_ROWS); + vec![vec![]] + } +} + +impl From for Data { + fn from(text: Text) -> Data { + match text { + Text::Raw(raw) => raw.into(), + Text::Buffer(buffer) => buffer.into(), + } + } +} + +/// Encode command +impl From for Data { + fn from(cmd: Command) -> Self { + match cmd { + Command::Reset => vec![vec![0x08, 0x00]], + Command::Clear => vec![vec![0x02, 0x00]], + Command::Reboot => vec![vec![0x0b, 0x00]], + Command::Fadeout => vec![vec![0x0d, 0x00]], + Command::Text(text) => text.into(), + } + } +} + +#[cfg(test)] +mod tests { + use super::{Command, Data, Text, TextRaw, Window}; + + #[test] + fn frame_data_from_text_command() { + let cmd = Command::Text(Text::Raw(TextRaw(Window::position(1, 2), "text123".into()))); + let data: Data = cmd.into(); + println!("data: {:?}", data) + } +} diff --git a/airportdisplay/src/display/window.rs b/airportdisplay/src/display/window.rs new file mode 100644 index 0000000..6554e09 --- /dev/null +++ b/airportdisplay/src/display/window.rs @@ -0,0 +1,27 @@ +/// A window for luminance and text commands +pub struct Window { + pub x: u16, // 0..55 + pub y: u16, // 0..19 + pub w: u16, // 1..56 + pub h: u16, // 1..20 +} + +impl Window { + pub fn new(x: u16, y: u16, w: u16, h: u16) -> Self { + Window { + x: x, + y: y, + w: w, + h: h, + } + } + + pub fn position(x: u16, y: u16) -> Self { + Window { + x: x, + y: y, + w: 0, + h: 0, + } + } +} diff --git a/airportdisplay/src/lib.rs b/airportdisplay/src/lib.rs new file mode 100644 index 0000000..d4e9f48 --- /dev/null +++ b/airportdisplay/src/lib.rs @@ -0,0 +1,3 @@ +mod display; + +pub use display::commands::{Command, Text}; diff --git a/hello_display/.gitignore b/hello_display/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/hello_display/.gitignore @@ -0,0 +1 @@ +/target diff --git a/hello_display/Cargo.lock b/hello_display/Cargo.lock new file mode 100644 index 0000000..70b9092 --- /dev/null +++ b/hello_display/Cargo.lock @@ -0,0 +1,30 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "airportdisplay" +version = "0.1.0" +dependencies = [ + "bytes", +] + +[[package]] +name = "anyhow" +version = "1.0.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305" + +[[package]] +name = "bytes" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" + +[[package]] +name = "hello_display" +version = "0.1.0" +dependencies = [ + "airportdisplay", + "anyhow", +] diff --git a/hello_display/Cargo.toml b/hello_display/Cargo.toml new file mode 100644 index 0000000..ae7f489 --- /dev/null +++ b/hello_display/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "hello_display" +version = "0.1.0" +edition = "2021" + + +[dependencies] +anyhow = "1" + +airportdisplay = { path = "../airportdisplay" } + diff --git a/hello_display/src/main.rs b/hello_display/src/main.rs new file mode 100644 index 0000000..04bff4d --- /dev/null +++ b/hello_display/src/main.rs @@ -0,0 +1,16 @@ +use anyhow::Result; + +use std::net::UdpSocket; + +fn main() -> Result<()> { + println!("Sending hello display..."); + + let socket = UdpSocket::bind("0.0.0.0:17382")?; + + + for frame in frames { + socket.send_to(frame, " + } + + Ok(()) +}