From 373725c648e104b55373fc6d0184c257ca022067 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Mon, 5 May 2025 22:55:18 +0200 Subject: [PATCH] add first specific commands --- cbindgen.toml | 2 +- include/servicepoint.h | 135 ++++++++++++++++++++++++++++++--- src/commands/bitmap_command.rs | 110 +++++++++++++++++++++++++++ src/commands/bitvec_command.rs | 115 ++++++++++++++++++++++++++++ src/commands/mod.rs | 2 + src/lib.rs | 4 + src/typed_command.rs | 58 +------------- 7 files changed, 360 insertions(+), 66 deletions(-) create mode 100644 src/commands/bitmap_command.rs create mode 100644 src/commands/bitvec_command.rs create mode 100644 src/commands/mod.rs diff --git a/cbindgen.toml b/cbindgen.toml index 221e915..68723da 100644 --- a/cbindgen.toml +++ b/cbindgen.toml @@ -32,7 +32,7 @@ features = ["full"] [export] include = [] -exclude = [] +exclude = ["BitVec"] [export.rename] "SpBitVec" = "BitVec" diff --git a/include/servicepoint.h b/include/servicepoint.h index 5863ef5..8923756 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -179,6 +179,22 @@ enum CompressionCode typedef uint16_t CompressionCode; #endif // __cplusplus +/** + * Set pixel data starting at the pixel offset on screen. + * + * 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. + * + * The [`BinaryOperation`] will be applied on the display comparing old and sent bit. + * + * `new_bit = old_bit op sent_bit` + * + * For example, [`BinaryOperation::Or`] can be used to turn on some pixels without affecting other pixels. + * + * The contained [`DisplayBitVec`] is always uncompressed. + */ +typedef struct BitVecCommand BitVecCommand; + /** * A fixed-size 2D grid of booleans. * @@ -196,6 +212,38 @@ typedef uint16_t CompressionCode; */ typedef struct Bitmap Bitmap; +/** + * Overwrites a rectangular region of pixels. + * + * Origin coordinates must be divisible by 8. + * + * # Examples + * + * ```rust + * # use servicepoint::*; + * # let connection = FakeConnection; + * # + * let mut bitmap = Bitmap::max_sized(); + * // draw something to the pixels here + * # bitmap.set(2, 5, true); + * + * // create command to send pixels + * let command = BitmapCommand { + * bitmap, + * origin: Origin::ZERO, + * compression: CompressionCode::Uncompressed + * }; + * + * connection.send_command(command).expect("send failed"); + * ``` + */ +typedef struct BitmapCommand BitmapCommand; + +/** + * This is a type only used by cbindgen to have a type for pointers. + */ +typedef struct DisplayBitVec DisplayBitVec; + /** * The raw packet. * @@ -348,6 +396,11 @@ typedef uint8_t Brightness; */ typedef ValueGrid_char CharGrid; +/** + * Type alias for documenting the meaning of the u16 in enum values + */ +typedef size_t Offset; + /** * A grid containing codepage 437 characters. * @@ -908,17 +961,64 @@ void sp_char_grid_set(CharGrid */*notnull*/ char_grid, */ size_t sp_char_grid_width(CharGrid */*notnull*/ char_grid); +BitmapCommand */*notnull*/ sp_cmd_bitmap_from_bitmap(Bitmap */*notnull*/ bitmap); + +/** + * Returns a pointer to the provided `BitmapCommand`. + * + * # Safety + * + * - The returned bitmap inherits the lifetime of the command in which it is contained. + * - The returned pointer may not be used in a function that consumes the instance, e.g. to create a command. + */ +Bitmap */*notnull*/ sp_cmd_bitmap_get(BitmapCommand */*notnull*/ command); + +CompressionCode sp_cmd_bitmap_get_compression(BitmapCommand */*notnull*/ command); + +void sp_cmd_bitmap_get_origin(BitmapCommand */*notnull*/ command, + size_t */*notnull*/ origin_x, + size_t */*notnull*/ origin_y); + +Packet *sp_cmd_bitmap_into_packet(BitmapCommand */*notnull*/ command); + +TypedCommand */*notnull*/ sp_cmd_bitmap_into_typed(BitmapCommand */*notnull*/ command); + /** * Sets a window of pixels to the specified values. * * The passed [Bitmap] gets consumed. * - * Returns: a new [servicepoint::BitmapCommand] instance. + * Returns: a new [BitmapCommand] instance. */ -TypedCommand *sp_command_bitmap(size_t x, - size_t y, - Bitmap */*notnull*/ bitmap, - CompressionCode compression); +BitmapCommand */*notnull*/ sp_cmd_bitmap_new(Bitmap */*notnull*/ bitmap, + size_t origin_x, + size_t origin_y, + CompressionCode compression); + +/** + * Moves the provided bitmap to be contained in the command. + */ +void sp_cmd_bitmap_set(BitmapCommand */*notnull*/ command, + Bitmap */*notnull*/ bitmap); + +void sp_cmd_bitmap_set_compression(BitmapCommand */*notnull*/ command, + CompressionCode compression); + +void sp_cmd_bitmap_set_origin(BitmapCommand */*notnull*/ command, + size_t origin_x, + size_t origin_y); + +DisplayBitVec *sp_cmd_bitvec_get(BitVecCommand */*notnull*/ command); + +CompressionCode sp_cmd_bitvec_get_compression(BitVecCommand */*notnull*/ command); + +Offset sp_cmd_bitvec_get_offset(BitVecCommand */*notnull*/ command); + +BinaryOperation sp_cmd_bitvec_get_operation(BitVecCommand */*notnull*/ command); + +Packet *sp_cmd_bitvec_into_packet(BitVecCommand */*notnull*/ command); + +TypedCommand */*notnull*/ sp_cmd_bitvec_into_typed(BitVecCommand */*notnull*/ command); /** * Set pixel data starting at the pixel offset on screen. @@ -932,12 +1032,27 @@ TypedCommand *sp_command_bitmap(size_t x, * * For example, [`BinaryOperation::Or`] can be used to turn on some pixels without affecting other pixels. * - * The contained [`BitVecU8Msb0`] is always uncompressed. + * The contained [`DisplayBitVec`] is always uncompressed. */ -TypedCommand *sp_command_bitvec(size_t offset, - SPBitVec */*notnull*/ bit_vec, - CompressionCode compression, - BinaryOperation operation); +BitVecCommand */*notnull*/ sp_cmd_bitvec_new(DisplayBitVec */*notnull*/ bitvec, + size_t offset, + BinaryOperation operation, + CompressionCode compression); + +/** + * Moves the provided bitmap to be contained in the command. + */ +void sp_cmd_bitvec_set(BitVecCommand */*notnull*/ command, + DisplayBitVec */*notnull*/ bitvec); + +void sp_cmd_bitvec_set_compression(BitVecCommand */*notnull*/ command, + CompressionCode compression); + +void sp_cmd_bitvec_set_offset(BitVecCommand */*notnull*/ command, + Offset offset); + +void sp_cmd_bitvec_set_operation(BitVecCommand */*notnull*/ command, + BinaryOperation operation); /** * Set the brightness of individual tiles in a rectangular area of the display. diff --git a/src/commands/bitmap_command.rs b/src/commands/bitmap_command.rs new file mode 100644 index 0000000..b1ab343 --- /dev/null +++ b/src/commands/bitmap_command.rs @@ -0,0 +1,110 @@ +use crate::{heap_move_nonnull, heap_move_ok, heap_remove}; +use servicepoint::{ + Bitmap, BitmapCommand, CompressionCode, Origin, Packet, TypedCommand, +}; +use std::ptr::NonNull; + +/// Sets a window of pixels to the specified values. +/// +/// The passed [Bitmap] gets consumed. +/// +/// Returns: a new [BitmapCommand] instance. +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_new( + bitmap: NonNull, + origin_x: usize, + origin_y: usize, + compression: CompressionCode, +) -> NonNull { + heap_move_nonnull(BitmapCommand { + bitmap: unsafe { heap_remove(bitmap) }, + origin: Origin::new(origin_x, origin_y), + compression, + }) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_from_bitmap( + bitmap: NonNull, +) -> NonNull { + heap_move_nonnull(unsafe { heap_remove(bitmap) }.into()) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_into_typed( + command: NonNull, +) -> NonNull { + heap_move_nonnull(unsafe { heap_remove(command) }.into()) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_into_packet( + command: NonNull, +) -> *mut Packet { + heap_move_ok(unsafe { heap_remove(command) }.try_into()) +} + +/// Returns a pointer to the provided `BitmapCommand`. +/// +/// # Safety +/// +/// - The returned bitmap inherits the lifetime of the command in which it is contained. +/// - The returned pointer may not be used in a function that consumes the instance, e.g. to create a command. +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_get( + mut command: NonNull, +) -> NonNull { + unsafe { NonNull::from(&mut (command.as_mut().bitmap)) } +} + +/// Moves the provided bitmap to be contained in the command. +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_set( + mut command: NonNull, + bitmap: NonNull, +) { + unsafe { + command.as_mut().bitmap = heap_remove(bitmap); + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_get_origin( + command: NonNull, + origin_x: NonNull, + origin_y: NonNull, +) { + unsafe { + let origin = &command.as_ref().origin; + *origin_x.as_ptr() = origin.x; + *origin_y.as_ptr() = origin.y; + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_set_origin( + mut command: NonNull, + origin_x: usize, + origin_y: usize, +) { + unsafe { + command.as_mut().origin = Origin::new(origin_x, origin_y); + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_set_compression( + mut command: NonNull, + compression: CompressionCode, +) { + unsafe { + command.as_mut().compression = compression; + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_get_compression( + command: NonNull, +) -> CompressionCode { + unsafe { command.as_ref().compression } +} diff --git a/src/commands/bitvec_command.rs b/src/commands/bitvec_command.rs new file mode 100644 index 0000000..39d5253 --- /dev/null +++ b/src/commands/bitvec_command.rs @@ -0,0 +1,115 @@ +use crate::{heap_move_nonnull, heap_move_ok, heap_remove}; +use servicepoint::{ + BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Offset, + Packet, TypedCommand, +}; +use std::ptr::NonNull; + +/// Set pixel data starting at the pixel offset on screen. +/// +/// 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. +/// +/// The [`BinaryOperation`] will be applied on the display comparing old and sent bit. +/// +/// `new_bit = old_bit op sent_bit` +/// +/// For example, [`BinaryOperation::Or`] can be used to turn on some pixels without affecting other pixels. +/// +/// The contained [`DisplayBitVec`] is always uncompressed. +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_new( + bitvec: NonNull, + offset: usize, + operation: BinaryOperation, + compression: CompressionCode, +) -> NonNull { + heap_move_nonnull(BitVecCommand { + bitvec: unsafe { heap_remove(bitvec) }, + offset, + operation, + compression, + }) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_into_typed( + command: NonNull, +) -> NonNull { + heap_move_nonnull(unsafe { heap_remove(command) }.into()) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_into_packet( + command: NonNull, +) -> *mut Packet { + heap_move_ok(unsafe { heap_remove(command) }.try_into()) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_get( + mut command: NonNull, +) -> *mut DisplayBitVec { + &mut unsafe { command.as_mut() }.bitvec +} + +/// Moves the provided bitmap to be contained in the command. +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_set( + mut command: NonNull, + bitvec: NonNull, +) { + unsafe { + command.as_mut().bitvec = heap_remove(bitvec); + } +} +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_get_offset( + command: NonNull, +) -> Offset { + unsafe { command.as_ref().offset } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_set_offset( + mut command: NonNull, + offset: Offset, +) { + unsafe { + command.as_mut().offset = offset; + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_get_operation( + command: NonNull, +) -> BinaryOperation { + unsafe { command.as_ref().operation.clone() } // TODO remove clone +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_set_operation( + mut command: NonNull, + operation: BinaryOperation, +) { + unsafe { + command.as_mut().operation = operation; + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_set_compression( + mut command: NonNull, + compression: CompressionCode, +) { + unsafe { + command.as_mut().compression = compression; + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_get_compression( + command: NonNull, +) -> CompressionCode { + unsafe { command.as_ref().compression } +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs new file mode 100644 index 0000000..45489df --- /dev/null +++ b/src/commands/mod.rs @@ -0,0 +1,2 @@ +mod bitmap_command; +mod bitvec_command; diff --git a/src/lib.rs b/src/lib.rs index f69f0b3..924a729 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,7 @@ mod bitvec; mod brightness_grid; mod byte_slice; mod char_grid; +mod commands; mod cp437_grid; mod packet; mod typed_command; @@ -78,3 +79,6 @@ pub(crate) unsafe fn heap_remove(x: NonNull) -> T { /// This is a type only used by cbindgen to have a type for pointers. pub struct UdpSocket; + +/// This is a type only used by cbindgen to have a type for pointers. +pub struct DisplayBitVec; diff --git a/src/typed_command.rs b/src/typed_command.rs index df454c4..451c0b7 100644 --- a/src/typed_command.rs +++ b/src/typed_command.rs @@ -1,7 +1,7 @@ -use crate::{heap_drop, heap_move, heap_move_nonnull, heap_move_ok, SPBitVec}; +use crate::{heap_drop, heap_move_nonnull, heap_move_ok}; use servicepoint::{ - BinaryOperation, Bitmap, Brightness, BrightnessGrid, CharGrid, - CompressionCode, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand, + Brightness, BrightnessGrid, CharGrid, Cp437Grid, GlobalBrightnessCommand, + Packet, TypedCommand, }; use std::ptr::NonNull; @@ -92,36 +92,6 @@ pub unsafe extern "C" fn sp_command_brightness_grid( heap_move_nonnull(result) } -/// Set pixel data starting at the pixel offset on screen. -/// -/// 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. -/// -/// The [`BinaryOperation`] will be applied on the display comparing old and sent bit. -/// -/// `new_bit = old_bit op sent_bit` -/// -/// For example, [`BinaryOperation::Or`] can be used to turn on some pixels without affecting other pixels. -/// -/// The contained [`BitVecU8Msb0`] is always uncompressed. -#[no_mangle] -pub unsafe extern "C" fn sp_command_bitvec( - offset: usize, - bit_vec: NonNull, - compression: CompressionCode, - operation: BinaryOperation, -) -> *mut TypedCommand { - let bit_vec = unsafe { *Box::from_raw(bit_vec.as_ptr()) }; - let command = servicepoint::BitVecCommand { - offset, - operation, - bitvec: bit_vec.0, - compression, - } - .into(); - heap_move(command) -} - /// Show codepage 437 encoded text on the screen. /// /// The passed [Cp437Grid] gets consumed. @@ -162,28 +132,6 @@ pub unsafe extern "C" fn sp_command_char_grid( heap_move_nonnull(result) } -/// Sets a window of pixels to the specified values. -/// -/// The passed [Bitmap] gets consumed. -/// -/// Returns: a new [servicepoint::BitmapCommand] instance. -#[no_mangle] -pub unsafe extern "C" fn sp_command_bitmap( - x: usize, - y: usize, - bitmap: NonNull, - compression: CompressionCode, -) -> *mut TypedCommand { - let bitmap = unsafe { *Box::from_raw(bitmap.as_ptr()) }; - let command = servicepoint::BitmapCommand { - origin: servicepoint::Origin::new(x, y), - bitmap, - compression, - } - .into(); - heap_move(command) -} - /// Deallocates a [TypedCommand]. /// /// # Examples