ph-haptics 0.1.0

Host-compiled haptics DSL and no-std, no-alloc scheduling runtime modeling ERM and LRA motors using ph-curves
Documentation
//! `ph-haptics` is a `no_std`/`no_alloc` scheduling and motor-modeling runtime
//! for compiled haptic catalogs.
//!
//! It is not a hardware layer: the runtime models ERM and LRA motor behavior
//! (profiles, kicks, ramps, level clamping) and emits abstract [`DriveCommand`]
//! values with tickless wake deadlines. Consuming firmware maps those commands
//! onto its own PWM, GPIO, bus, or motor-driver hardware.
//!
//! Text/script compilation is handled by the `ph-haptics-gen` binary. Generated
//! assets use this crate's DSL/runtime types (`Program`, `Instruction`,
//! `CompiledHapticDef`, [`Runner`]) for execution. Curve shaping and tickless
//! transition timing come from `ph-curves`.
//!
//! # Features
//!
//! The default feature set is the embedded runtime and remains `no_std` and
//! `no_alloc`. The optional `gen` feature enables the host-only generator and
//! its `std`-based dependencies; never enable it in a firmware dependency.
//!
//! # Example
//!
//! Generated catalogs expose the same constants assembled explicitly below.
//! Firmware normally includes the generator output and starts a runner from its
//! `COMPILED_CATALOG` constant.
//!
//! ```
//! use ph_haptics::{
//!     CompiledCatalog, CompiledHapticDef, DriveCommand, ErmConfig, Instruction,
//!     MonotonicCurveLut256, MotorConfig, MotorKind, Program,
//! };
//!
//! let instructions = [Instruction::<MonotonicCurveLut256>::hold(10, u16::MAX)];
//! let program = Program::new(MotorKind::Erm, &instructions);
//! let definition = CompiledHapticDef::new("click", program, None);
//! let definitions = [definition];
//! let catalog = CompiledCatalog::new(&definitions);
//! let mut runner = catalog
//!     .runner_started("click", MotorConfig::Erm(ErmConfig::new(255)), 0)
//!     .unwrap();
//!
//! let frame = runner.poll(0);
//! assert_eq!(frame.command, DriveCommand::Erm { duty: 255 });
//! assert_eq!(frame.next_transition_ms, Some(10));
//! ```

#![no_std]
#![deny(missing_docs)]
#![forbid(unsafe_code)]
#![deny(unsafe_op_in_unsafe_fn)]
// Clippy lint levels live here; thresholds and config are in clippy.toml.
#![deny(clippy::correctness)]
#![deny(
    clippy::std_instead_of_core,
    clippy::std_instead_of_alloc,
    clippy::alloc_instead_of_core
)]
#![warn(
    clippy::suspicious,
    clippy::style,
    clippy::complexity,
    clippy::perf,
    clippy::cloned_instead_of_copied,
    clippy::explicit_iter_loop,
    clippy::implicit_clone,
    clippy::inconsistent_struct_constructor,
    clippy::manual_assert,
    clippy::manual_let_else,
    clippy::match_same_arms,
    clippy::needless_pass_by_value,
    clippy::semicolon_if_nothing_returned,
    clippy::uninlined_format_args,
    clippy::unnested_or_patterns
)]
#![allow(
    clippy::mod_module_files,
    clippy::self_named_module_files,
    clippy::similar_names,
    clippy::too_many_arguments,
    clippy::struct_excessive_bools,
    clippy::fn_params_excessive_bools,
    clippy::type_complexity,
    clippy::must_use_candidate,
    clippy::assertions_on_constants,
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_sign_loss,
    clippy::cast_precision_loss,
    clippy::cast_lossless,
    clippy::panic_in_result_fn,
    clippy::unwrap_used,
    clippy::expect_used,
    clippy::module_name_repetitions,
    clippy::wildcard_imports,
    clippy::items_after_statements,
    clippy::let_underscore_future
)]

/// Compiled haptic definition and catalog types.
pub mod compiled;
mod dsl;
/// Runtime/lookup error types.
pub mod error;
/// Motor models, profiles, and driver command types.
pub mod motor;
/// Haptics runner and frame evaluation.
pub mod runtime;

pub use compiled::{CompiledCatalog, CompiledCatalogError, CompiledHapticDef};
pub use dsl::{Instruction, LoopMode, Program, Ramp};
pub use error::Error;
pub use motor::{
    DEFAULT_ERM_PROFILE, DEFAULT_LRA_PROFILE, DriveCommand, ErmConfig, LraConfig, MotorConfig,
    MotorKind, MotorProfile,
};
pub use runtime::{Frame, Runner};

pub use ph_curves::{
    self, Curve, MonotonicCurve, MonotonicCurveLut, MonotonicCurveLut256, Rounding, Tickless,
    TicklessDeadline, TicklessSchedule, UnitValue,
};

#[cfg(test)]
extern crate std;