//! CAN controller primitives for actuator and motor control.
//!
//! `kcan` provides the hardware-independent protocol pieces needed to control
//! CAN-connected actuators: frame packing, feedback decoding, safety clamping,
//! unit conversion, and control-loop helpers.
//!
//! Build a CubeMars MIT frame without opening a CAN device:
//!
//! ```
//! # fn main() -> kcan::Result<()> {
//! use kcan::{MitCommand, MotorModel, mit_command_frame};
//!
//! let frame = mit_command_frame(MotorModel::Ak60_6, 0x03, MitCommand::neutral())?;
//!
//! assert_eq!(frame.id().raw(), 0x0803);
//! assert_eq!(frame.len(), 8);
//! # Ok(())
//! # }
//! ```
//!
//! Build a RobStride status query frame:
//!
//! ```
//! # fn main() -> kcan::Result<()> {
//! use kcan::{RobStrideModel, robstride_status_query_frame};
//!
//! let model: RobStrideModel = "rs01".parse()?;
//! let frame = robstride_status_query_frame(0x01)?;
//!
//! assert_eq!(model, RobStrideModel::Rs01);
//! assert_eq!(frame.id().raw(), 0x501);
//! # Ok(())
//! # }
//! ```
//!
//! Optional features are disabled by default. Enable `serde` for
//! serialization, `socketcan` for Linux SocketCAN transport, and `tui` for the
//! Scrin/Scrin Widgets dashboards.

#![forbid(unsafe_code)]

pub mod actuator;
pub mod bus;
pub mod control;
pub mod error;
pub mod manager;
pub mod monitor;
pub mod motor;
pub mod protocol;
pub mod protocols;
#[cfg(feature = "socketcan")]
pub mod socketcan_transport;
#[cfg(feature = "tui")]
pub mod tui;

pub use actuator::{
    ActuatorConfig, ActuatorFeedback, ActuatorHealth, ActuatorMetric, ActuatorProtocol,
    ActuatorSnapshot,
};
pub use bus::{CanBus, CanFrame, CanId};
pub use control::{
    LowPassFilterConfig, PIDConfig, PIDController, SecondOrderLowPassFilter, SolverType,
};
pub use error::{Error, Result};
pub use manager::MotorManager;
pub use monitor::{
    CAN_TRACE_CSV_HEADER, CanFrameClass, CanFrameRecord, CanMonitor, CanMonitorStats,
    CanTraceRecord, FormattedCanFrame, parse_can_trace_csv, replay_can_trace, sample_can_monitor,
};
pub use motor::{HelperPolicy, MotorConfig, MotorController, RefreshStats};
pub use protocol::{
    ControlMode, DirectCommand, DirectPayload, FaultCode, FeedbackFilter, MitCommand,
    MitHelperCommand, MitLimits, MotorFeedback, MotorModel, MotorSpec, OriginMode,
    SUPPORTED_MOTOR_MODELS, direct_command_frame, mit_command_frame, mit_helper_frame,
    pack_mit_command,
};
pub use protocols::robstride::{
    ROBSTRIDE_MODELS, RobStrideCommand, RobStrideFeedback, RobStrideFrameKind, RobStrideMitCommand,
    RobStrideModel, RobStridePositionCommand, RobStrideRawCommand, RobStrideSpec,
    RobStrideSpeedCommand, robstride_command_frame, robstride_status_query_frame,
};
#[cfg(feature = "socketcan")]
pub use socketcan_transport::SocketCanBus;
#[cfg(feature = "tui")]
pub use tui::{
    CanMonitorCommand, TuiCanMonitor, TuiCommand, TuiControlIntent, TuiDashboard, TuiMode,
    TuiTarget,
};
