mirror of
https://github.com/cccb/servicepoint.git
synced 2025-01-18 18:10:14 +01:00
add links to documentation, add some docs
This commit is contained in:
parent
d3e135e508
commit
26bace8990
|
@ -18,13 +18,36 @@ pub type Cp437Grid = PrimitiveGrid<u8>;
|
||||||
///
|
///
|
||||||
/// This struct and associated functions implement the UDP protocol for the display.
|
/// This struct and associated functions implement the UDP protocol for the display.
|
||||||
///
|
///
|
||||||
/// To send a `Command`, use a `Connection`.
|
/// To send a [Command], use a [connection][crate::Connection].
|
||||||
|
///
|
||||||
|
/// # Available commands
|
||||||
|
///
|
||||||
|
/// To send text, take a look at [Command::Cp437Data].
|
||||||
|
///
|
||||||
|
/// To draw pixels, the easiest command to use is [Command::BitmapLinearWin].
|
||||||
|
///
|
||||||
|
/// The other BitmapLinear-Commands operate on a region of pixel memory directly.
|
||||||
|
/// [Command::BitmapLinear] overwrites a region.
|
||||||
|
/// [Command::BitmapLinearOr], [Command::BitmapLinearAnd] and [Command::BitmapLinearXor] apply logical operations per pixel.
|
||||||
|
///
|
||||||
|
/// Out of bounds operations may be truncated or ignored by the display.
|
||||||
|
///
|
||||||
|
/// # Compression
|
||||||
|
///
|
||||||
|
/// Some commands can contain compressed payloads.
|
||||||
|
/// To get started, use [CompressionCode::Uncompressed].
|
||||||
|
///
|
||||||
|
/// If you want to archive the best performance (e.g. latency),
|
||||||
|
/// you can try the different compression algorithms for your hardware and use case.
|
||||||
|
///
|
||||||
|
/// In memory, the payload is not compressed in the [Command].
|
||||||
|
/// Payload (de-)compression happens when converting the [Command] into a [Packet] or vice versa.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use servicepoint::{Brightness, Command, Connection, Packet};
|
/// # use servicepoint::{Brightness, Command, Connection, Packet};
|
||||||
///
|
/// #
|
||||||
/// // create command
|
/// // create command
|
||||||
/// let command = Command::Brightness(Brightness::MAX);
|
/// let command = Command::Brightness(Brightness::MAX);
|
||||||
///
|
///
|
||||||
|
@ -56,6 +79,8 @@ pub enum Command {
|
||||||
|
|
||||||
/// Show text on the screen.
|
/// Show text on the screen.
|
||||||
///
|
///
|
||||||
|
/// The text is sent in the form of a 2D grid of characters.
|
||||||
|
///
|
||||||
/// <div class="warning">
|
/// <div class="warning">
|
||||||
/// The library does not currently convert between UTF-8 and CP-437.
|
/// The library does not currently convert between UTF-8 and CP-437.
|
||||||
/// Because Rust expects UTF-8 strings, it might be necessary to only send ASCII for now.
|
/// Because Rust expects UTF-8 strings, it might be necessary to only send ASCII for now.
|
||||||
|
@ -72,7 +97,29 @@ pub enum Command {
|
||||||
/// ```
|
/// ```
|
||||||
Cp437Data(Origin<Tiles>, Cp437Grid),
|
Cp437Data(Origin<Tiles>, Cp437Grid),
|
||||||
|
|
||||||
/// Sets a window of pixels to the specified values
|
/// Overwrites a rectangular region of pixels.
|
||||||
|
///
|
||||||
|
/// Origin coordinates must be divisible by 8.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use servicepoint::{Command, CompressionCode, Grid, PixelGrid};
|
||||||
|
/// # let connection = servicepoint::Connection::Fake;
|
||||||
|
/// #
|
||||||
|
/// let mut pixels = PixelGrid::max_sized();
|
||||||
|
/// // draw something to the pixels here
|
||||||
|
/// # pixels.set(2, 5, true);
|
||||||
|
///
|
||||||
|
/// // create command to send pixels
|
||||||
|
/// let command = Command::BitmapLinearWin(
|
||||||
|
/// servicepoint::Origin::new(0, 0),
|
||||||
|
/// pixels,
|
||||||
|
/// CompressionCode::Uncompressed
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// connection.send(command).expect("send failed");
|
||||||
|
/// ```
|
||||||
BitmapLinearWin(Origin<Pixels>, PixelGrid, CompressionCode),
|
BitmapLinearWin(Origin<Pixels>, PixelGrid, CompressionCode),
|
||||||
|
|
||||||
/// Set the brightness of all tiles to the same value.
|
/// Set the brightness of all tiles to the same value.
|
||||||
|
@ -95,7 +142,7 @@ pub enum Command {
|
||||||
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
|
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
|
||||||
/// once the starting row is full, overwriting will continue on column 0.
|
/// once the starting row is full, overwriting will continue on column 0.
|
||||||
///
|
///
|
||||||
/// The contained `BitVec` is always uncompressed.
|
/// The contained [BitVec] is always uncompressed.
|
||||||
BitmapLinear(Offset, SpBitVec, CompressionCode),
|
BitmapLinear(Offset, SpBitVec, CompressionCode),
|
||||||
|
|
||||||
/// Set pixel data according to an and-mask starting at the offset.
|
/// Set pixel data according to an and-mask starting at the offset.
|
||||||
|
@ -103,7 +150,7 @@ pub enum Command {
|
||||||
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
|
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
|
||||||
/// once the starting row is full, overwriting will continue on column 0.
|
/// once the starting row is full, overwriting will continue on column 0.
|
||||||
///
|
///
|
||||||
/// The contained `BitVec` is always uncompressed.
|
/// The contained [BitVec] is always uncompressed.
|
||||||
BitmapLinearAnd(Offset, SpBitVec, CompressionCode),
|
BitmapLinearAnd(Offset, SpBitVec, CompressionCode),
|
||||||
|
|
||||||
/// Set pixel data according to an or-mask starting at the offset.
|
/// Set pixel data according to an or-mask starting at the offset.
|
||||||
|
@ -111,7 +158,7 @@ pub enum Command {
|
||||||
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
|
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
|
||||||
/// once the starting row is full, overwriting will continue on column 0.
|
/// once the starting row is full, overwriting will continue on column 0.
|
||||||
///
|
///
|
||||||
/// The contained `BitVec` is always uncompressed.
|
/// The contained [BitVec] is always uncompressed.
|
||||||
BitmapLinearOr(Offset, SpBitVec, CompressionCode),
|
BitmapLinearOr(Offset, SpBitVec, CompressionCode),
|
||||||
|
|
||||||
/// Set pixel data according to a xor-mask starting at the offset.
|
/// Set pixel data according to a xor-mask starting at the offset.
|
||||||
|
@ -119,7 +166,7 @@ pub enum Command {
|
||||||
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
|
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
|
||||||
/// once the starting row is full, overwriting will continue on column 0.
|
/// once the starting row is full, overwriting will continue on column 0.
|
||||||
///
|
///
|
||||||
/// The contained `BitVec` is always uncompressed.
|
/// The contained [BitVec] is always uncompressed.
|
||||||
BitmapLinearXor(Offset, SpBitVec, CompressionCode),
|
BitmapLinearXor(Offset, SpBitVec, CompressionCode),
|
||||||
|
|
||||||
/// Kills the udp daemon on the display, which usually results in a restart.
|
/// Kills the udp daemon on the display, which usually results in a restart.
|
||||||
|
@ -166,7 +213,7 @@ pub enum Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Err values for `Command::try_from`.
|
/// Err values for [Command::try_from].
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum TryFromPacketError {
|
pub enum TryFromPacketError {
|
||||||
/// the contained command code does not correspond to a known command
|
/// the contained command code does not correspond to a known command
|
||||||
|
@ -188,7 +235,7 @@ pub enum TryFromPacketError {
|
||||||
impl TryFrom<Packet> for Command {
|
impl TryFrom<Packet> for Command {
|
||||||
type Error = TryFromPacketError;
|
type Error = TryFromPacketError;
|
||||||
|
|
||||||
/// Try to interpret the `Packet` as one containing a `Command`
|
/// Try to interpret the [Packet] as one containing a [Command]
|
||||||
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
||||||
let Packet {
|
let Packet {
|
||||||
header: Header {
|
header: Header {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/// The u16 command codes used for the `Commands`.
|
/// The u16 command codes used for the [Command]s.
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub(crate) enum CommandCode {
|
pub(crate) enum CommandCode {
|
||||||
|
|
|
@ -7,6 +7,8 @@ use crate::Packet;
|
||||||
|
|
||||||
/// A connection to the display.
|
/// A connection to the display.
|
||||||
///
|
///
|
||||||
|
/// Used to send [Packets][Packet] or [Commands][crate::Command].
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let connection = servicepoint::Connection::open("172.23.42.29:2342")
|
/// let connection = servicepoint::Connection::open("172.23.42.29:2342")
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
//! Abstractions for the UDP protocol of the CCCB servicepoint display.
|
//! Abstractions for the UDP protocol of the CCCB servicepoint display.
|
||||||
//!
|
//!
|
||||||
|
//! Your starting point is a [Connection] to the display.
|
||||||
|
//! With a connection, you can send [Command]s.
|
||||||
|
//! When received, the display will update the state of the pixels.
|
||||||
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub struct Origin<Unit: DisplayUnit> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Unit: DisplayUnit> Origin<Unit> {
|
impl<Unit: DisplayUnit> Origin<Unit> {
|
||||||
/// Create a new `Origin` instance for the provided position.
|
/// Create a new [Origin] instance for the provided position.
|
||||||
pub fn new(x: usize, y: usize) -> Self {
|
pub fn new(x: usize, y: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
x,
|
x,
|
||||||
|
|
|
@ -38,6 +38,8 @@ pub type Payload = Vec<u8>;
|
||||||
///
|
///
|
||||||
/// Contents should probably only be used directly to use features not exposed by the library.
|
/// Contents should probably only be used directly to use features not exposed by the library.
|
||||||
///
|
///
|
||||||
|
/// You may want to use [Command][crate::Command] instead.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Converting a packet to a command and back:
|
/// Converting a packet to a command and back:
|
||||||
|
@ -46,7 +48,7 @@ pub type Payload = Vec<u8>;
|
||||||
/// # use servicepoint::{Command, Packet};
|
/// # use servicepoint::{Command, Packet};
|
||||||
/// # let command = Command::Clear;
|
/// # let command = Command::Clear;
|
||||||
/// let packet: Packet = command.into();
|
/// let packet: Packet = command.into();
|
||||||
/// let command: Command = Command::try_from(packet).expect("could not read packet");
|
/// let command: Command = Command::try_from(packet).expect("could not read command from packet");
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Converting a packet to bytes and back:
|
/// Converting a packet to bytes and back:
|
||||||
|
@ -98,9 +100,9 @@ impl From<Packet> for Vec<u8> {
|
||||||
impl TryFrom<&[u8]> for Packet {
|
impl TryFrom<&[u8]> for Packet {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
/// Tries to interpret the bytes as a `Packet`.
|
/// Tries to interpret the bytes as a [Packet].
|
||||||
///
|
///
|
||||||
/// returns: `Error` if slice is not long enough to be a `Packet`
|
/// returns: `Error` if slice is not long enough to be a [Packet]
|
||||||
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
|
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
|
||||||
if value.len() < size_of::<Header>() {
|
if value.len() < size_of::<Header>() {
|
||||||
return Err(());
|
return Err(());
|
||||||
|
@ -135,7 +137,7 @@ impl TryFrom<Vec<u8>> for Packet {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Command> for Packet {
|
impl From<Command> for Packet {
|
||||||
/// Move the `Command` into a `Packet` instance for sending.
|
/// Move the [Command] into a [Packet] instance for sending.
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
fn from(value: Command) -> Self {
|
fn from(value: Command) -> Self {
|
||||||
match value {
|
match value {
|
||||||
|
@ -210,7 +212,7 @@ impl From<Command> for Packet {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Packet {
|
impl Packet {
|
||||||
/// Helper method for `BitMapLinear*`-Commands into `Packet`
|
/// Helper method for `BitMapLinear*`-Commands into [Packet]
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
fn bitmap_linear_into_packet(
|
fn bitmap_linear_into_packet(
|
||||||
command: CommandCode,
|
command: CommandCode,
|
||||||
|
|
|
@ -13,14 +13,14 @@ pub struct PixelGrid {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PixelGrid {
|
impl PixelGrid {
|
||||||
/// Creates a new `PixelGrid` with the specified dimensions.
|
/// Creates a new [PixelGrid] with the specified dimensions.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// - `width`: size in pixels in x-direction
|
/// - `width`: size in pixels in x-direction
|
||||||
/// - `height`: size in pixels in y-direction
|
/// - `height`: size in pixels in y-direction
|
||||||
///
|
///
|
||||||
/// returns: `PixelGrid` initialized to all pixels off
|
/// returns: [PixelGrid] initialized to all pixels off
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
|
@ -40,14 +40,14 @@ impl PixelGrid {
|
||||||
Self::new(PIXEL_WIDTH, PIXEL_HEIGHT)
|
Self::new(PIXEL_WIDTH, PIXEL_HEIGHT)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a `PixelGrid` with the specified dimensions from the provided data.
|
/// Loads a [PixelGrid] with the specified dimensions from the provided data.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// - `width`: size in pixels in x-direction
|
/// - `width`: size in pixels in x-direction
|
||||||
/// - `height`: size in pixels in y-direction
|
/// - `height`: size in pixels in y-direction
|
||||||
///
|
///
|
||||||
/// returns: `PixelGrid` that contains a copy of the provided data
|
/// returns: [PixelGrid] that contains a copy of the provided data
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
|
@ -64,7 +64,7 @@ impl PixelGrid {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all cells in `PixelGrid`.
|
/// Iterate over all cells in [PixelGrid].
|
||||||
///
|
///
|
||||||
/// Order is equivalent to the following loop:
|
/// Order is equivalent to the following loop:
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -80,7 +80,7 @@ impl PixelGrid {
|
||||||
self.bit_vec.iter().by_refs()
|
self.bit_vec.iter().by_refs()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all cells in `PixelGrid` mutably.
|
/// Iterate over all cells in [PixelGrid] mutably.
|
||||||
///
|
///
|
||||||
/// Order is equivalent to the following loop:
|
/// Order is equivalent to the following loop:
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -107,7 +107,7 @@ impl PixelGrid {
|
||||||
self.bit_vec.iter_mut()
|
self.bit_vec.iter_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all rows in `PixelGrid` top to bottom.
|
/// Iterate over all rows in [PixelGrid] top to bottom.
|
||||||
pub fn iter_rows(&self) -> IterRows {
|
pub fn iter_rows(&self) -> IterRows {
|
||||||
IterRows {
|
IterRows {
|
||||||
pixel_grid: self,
|
pixel_grid: self,
|
||||||
|
@ -117,7 +117,7 @@ impl PixelGrid {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Grid<bool> for PixelGrid {
|
impl Grid<bool> for PixelGrid {
|
||||||
/// Sets the value of the specified position in the `PixelGrid`.
|
/// Sets the value of the specified position in the [PixelGrid].
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
|
@ -139,7 +139,7 @@ impl Grid<bool> for PixelGrid {
|
||||||
self.bit_vec[x + y * self.width]
|
self.bit_vec[x + y * self.width]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the state of all pixels in the `PixelGrid`.
|
/// Sets the state of all pixels in the [PixelGrid].
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
|
@ -169,7 +169,7 @@ impl DataRef<u8> for PixelGrid {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<PixelGrid> for Vec<u8> {
|
impl From<PixelGrid> for Vec<u8> {
|
||||||
/// Turns a `PixelGrid` into the underlying `Vec<u8>`.
|
/// Turns a [PixelGrid] into the underlying [`Vec<u8>`].
|
||||||
fn from(value: PixelGrid) -> Self {
|
fn from(value: PixelGrid) -> Self {
|
||||||
value.bit_vec.into()
|
value.bit_vec.into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,14 @@ pub struct PrimitiveGrid<T: PrimitiveGridType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PrimitiveGridType> PrimitiveGrid<T> {
|
impl<T: PrimitiveGridType> PrimitiveGrid<T> {
|
||||||
/// Creates a new `PrimitiveGrid` with the specified dimensions.
|
/// Creates a new [PrimitiveGrid] with the specified dimensions.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// - width: size in x-direction
|
/// - width: size in x-direction
|
||||||
/// - height: size in y-direction
|
/// - height: size in y-direction
|
||||||
///
|
///
|
||||||
/// returns: `PrimitiveGrid` initialized to default value.
|
/// returns: [PrimitiveGrid] initialized to default value.
|
||||||
pub fn new(width: usize, height: usize) -> Self {
|
pub fn new(width: usize, height: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
data: vec![Default::default(); width * height],
|
data: vec![Default::default(); width * height],
|
||||||
|
@ -30,9 +30,9 @@ impl<T: PrimitiveGridType> PrimitiveGrid<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a `PrimitiveGrid` with the specified dimensions from the provided data.
|
/// Loads a [PrimitiveGrid] with the specified dimensions from the provided data.
|
||||||
///
|
///
|
||||||
/// returns: `PrimitiveGrid` that contains a copy of the provided data
|
/// returns: [PrimitiveGrid] that contains a copy of the provided data
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
|
@ -47,7 +47,7 @@ impl<T: PrimitiveGridType> PrimitiveGrid<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all cells in `PrimitiveGrid`.
|
/// Iterate over all cells in [PrimitiveGrid].
|
||||||
///
|
///
|
||||||
/// Order is equivalent to the following loop:
|
/// Order is equivalent to the following loop:
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -63,7 +63,7 @@ impl<T: PrimitiveGridType> PrimitiveGrid<T> {
|
||||||
self.data.iter()
|
self.data.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all rows in `PrimitiveGrid` top to bottom.
|
/// Iterate over all rows in [PrimitiveGrid] top to bottom.
|
||||||
pub fn iter_rows(&self) -> IterRows<T> {
|
pub fn iter_rows(&self) -> IterRows<T> {
|
||||||
IterRows {
|
IterRows {
|
||||||
byte_grid: self,
|
byte_grid: self,
|
||||||
|
@ -168,7 +168,7 @@ impl<T: PrimitiveGridType> DataRef<T> for PrimitiveGrid<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PrimitiveGridType> From<PrimitiveGrid<T>> for Vec<T> {
|
impl<T: PrimitiveGridType> From<PrimitiveGrid<T>> for Vec<T> {
|
||||||
/// Turn into the underlying `Vec<u8>` containing the rows of bytes.
|
/// Turn into the underlying [`Vec<u8>`] containing the rows of bytes.
|
||||||
fn from(value: PrimitiveGrid<T>) -> Self {
|
fn from(value: PrimitiveGrid<T>) -> Self {
|
||||||
value.data
|
value.data
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue