Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix small errors #46

Merged
merged 6 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mil_std_1553b"
version = "0.3.0"
version = "0.3.1"
edition = "2021"
license = "MIT"
readme = "README.md"
Expand Down
80 changes: 68 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,85 @@ or military projects that can't have virally licensed dependencies.
* Has no dependencies.
* MIT licensed.

## Usage
## Basic usage

### Creating a message

A message can be built using the constructor methods of [Message], [CommandWord],
[StatusWord], and [DataWord].

```rust
# use mil_std_1553b::*;
# fn try_main() -> Result<()> {
use mil_std_1553b::*;

let message = Message::new()
.with_command(CommandWord::new()
.with_address(12)
.with_subaddress(5)
.with_word_count(2)
.build()?
)?
.with_data(DataWord::new())?
.with_data(DataWord::new())?;
.build().unwrap()
).unwrap()
.with_data(DataWord::new()).unwrap()
.with_data(DataWord::new()).unwrap();

assert!(message.is_full());
assert_eq!(message.word_count(),3);
assert_eq!(message.data_count(),2);
assert_eq!(message.data_expected(),2);
# Ok(())
# }
```

### Parsing a message

#### Command messages

Messages can be parsed as command messages, and the leading command word will determine
how many data words will be parsed from the buffer. See [Message] for more information.

```rust
use mil_std_1553b::*;

let message = Message::parse_command(&[
0b10000011,
0b00001100,
0b00100010,
0b11010000,
0b11010010
])
.unwrap();

assert_eq!(message.word_count(),2);
```

#### Status messages

See [Message] for more information.

```rust
use mil_std_1553b::*;

let message = Message::parse_status(&[
0b10000011,
0b00001100,
0b01000010,
0b11010000,
0b11010010
])
.unwrap();

assert_eq!(message.word_count(), 2);
```

### Parsing a word

Words can be parsed from two-byte byte arrays or u16s. Data words can also be created
from strings. See [WordType] for more information.

```rust
use mil_std_1553b::*;

let word = DataWord::new()
.with_bytes([0b01001000, 0b01001001])
.with_calculated_parity()
.build()
.unwrap();

assert_eq!(word.as_string(),Ok("HI"));
```

## Roadmap
Expand Down
71 changes: 36 additions & 35 deletions src/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/// Given a mask and offset, the Field struct can get
/// or set between 1 and 8 bits in a u16 word.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Field {
pub(crate) struct Field {
/// The mask used to isolate the value
mask: u16,

Expand All @@ -15,114 +15,115 @@ pub struct Field {

impl Field {
/// Create a new field given a mask
pub const fn new(mask: u16) -> Self {
pub(crate) const fn new(mask: u16) -> Self {
Self {
mask,
offset: mask.trailing_zeros(),
}
}

/// Read the value of the field from a data word
pub const fn get(&self, data: u16) -> u8 {
pub(crate) const fn get(&self, data: u16) -> u8 {
((data & self.mask) >> self.offset) as u8
}

/// Write the value of the field to a data word
pub const fn set(&self, data: u16, value: u8) -> u16 {
pub(crate) const fn set(&self, data: u16, value: u8) -> u16 {
let v = (value as u16) << self.offset;
(data & !self.mask) | (v & self.mask)
}
}

/// Mask for an empty field
pub const WORD_EMPTY: u16 = 0b0000000000000000;
#[cfg(test)]
pub(crate) const WORD_EMPTY: u16 = 0b0000000000000000;

/// Mask for parsing the terminal address of a command word.
pub const COMMAND_TERMINAL_ADDRESS: u16 = 0b1111100000000000;
pub(crate) const COMMAND_TERMINAL_ADDRESS: u16 = 0b1111100000000000;

/// Field definition for the terminal address of a command word.
pub const COMMAND_TERMINAL_ADDRESS_FIELD: Field = Field::new(COMMAND_TERMINAL_ADDRESS);
pub(crate) const COMMAND_TERMINAL_ADDRESS_FIELD: Field = Field::new(COMMAND_TERMINAL_ADDRESS);

/// Mask for parsing the transmit/receive flag of a command word.
pub const COMMAND_TRANSMIT_RECEIVE: u16 = 0b0000010000000000;
pub(crate) const COMMAND_TRANSMIT_RECEIVE: u16 = 0b0000010000000000;

/// Field definition for the transmit/receive flag of a command word.
pub const COMMAND_TRANSMIT_RECEIVE_FIELD: Field = Field::new(COMMAND_TRANSMIT_RECEIVE);
pub(crate) const COMMAND_TRANSMIT_RECEIVE_FIELD: Field = Field::new(COMMAND_TRANSMIT_RECEIVE);

/// Mask for parsing the terminal subaddress of a command word.
pub const COMMAND_SUBADDRESS: u16 = 0b0000001111100000;
pub(crate) const COMMAND_SUBADDRESS: u16 = 0b0000001111100000;

/// Field definition for the terminal subaddress of a command word.
pub const COMMAND_SUBADDRESS_FIELD: Field = Field::new(COMMAND_SUBADDRESS);
pub(crate) const COMMAND_SUBADDRESS_FIELD: Field = Field::new(COMMAND_SUBADDRESS);

/// Mask for parsing the mode code of a command word.
pub const COMMAND_MODE_CODE: u16 = 0b0000000000011111;
pub(crate) const COMMAND_MODE_CODE: u16 = 0b0000000000011111;

/// Field definition for the mode code of a command word.
pub const COMMAND_MODE_CODE_FIELD: Field = Field::new(COMMAND_MODE_CODE);
pub(crate) const COMMAND_MODE_CODE_FIELD: Field = Field::new(COMMAND_MODE_CODE);

/// Mask for parsing the word count of a command word.
pub const COMMAND_WORD_COUNT: u16 = 0b0000000000011111;
pub(crate) const COMMAND_WORD_COUNT: u16 = 0b0000000000011111;

/// Field definition for the word count of a command word.
pub const COMMAND_WORD_COUNT_FIELD: Field = Field::new(COMMAND_WORD_COUNT);
pub(crate) const COMMAND_WORD_COUNT_FIELD: Field = Field::new(COMMAND_WORD_COUNT);

/// Mask for parsing the terminal address of a status word.
pub const STATUS_TERMINAL_ADDRESS: u16 = 0b1111100000000000;
pub(crate) const STATUS_TERMINAL_ADDRESS: u16 = 0b1111100000000000;

/// Field definition for the terminal address of a status word.
pub const STATUS_TERMINAL_ADDRESS_FIELD: Field = Field::new(STATUS_TERMINAL_ADDRESS);
pub(crate) const STATUS_TERMINAL_ADDRESS_FIELD: Field = Field::new(STATUS_TERMINAL_ADDRESS);

/// Mask for parsing the error flag of a status word.
pub const STATUS_MESSAGE_ERROR: u16 = 0b0000010000000000;
pub(crate) const STATUS_MESSAGE_ERROR: u16 = 0b0000010000000000;

/// Field definition for the error flag of a status word.
pub const STATUS_MESSAGE_ERROR_FIELD: Field = Field::new(STATUS_MESSAGE_ERROR);
pub(crate) const STATUS_MESSAGE_ERROR_FIELD: Field = Field::new(STATUS_MESSAGE_ERROR);

/// Mask for parsing the instrumentation flag of a status word.
pub const STATUS_INSTRUMENTATION: u16 = 0b0000001000000000;
pub(crate) const STATUS_INSTRUMENTATION: u16 = 0b0000001000000000;

/// Field definition for the instrumentation flag of a status word.
pub const STATUS_INSTRUMENTATION_FIELD: Field = Field::new(STATUS_INSTRUMENTATION);
pub(crate) const STATUS_INSTRUMENTATION_FIELD: Field = Field::new(STATUS_INSTRUMENTATION);

/// Mask for parsing the service request flag of a status word.
pub const STATUS_SERVICE_REQUEST: u16 = 0b0000000100000000;
pub(crate) const STATUS_SERVICE_REQUEST: u16 = 0b0000000100000000;

/// Field definition for the service request flag of a status word.
pub const STATUS_SERVICE_REQUEST_FIELD: Field = Field::new(STATUS_SERVICE_REQUEST);
pub(crate) const STATUS_SERVICE_REQUEST_FIELD: Field = Field::new(STATUS_SERVICE_REQUEST);

/// Mask for parsing the reserved bits of a status word.
pub const STATUS_RESERVED_BITS: u16 = 0b0000000011100000;
pub(crate) const STATUS_RESERVED_BITS: u16 = 0b0000000011100000;

/// Field definition for the reserved bits of a status word.
pub const STATUS_RESERVED_BITS_FIELD: Field = Field::new(STATUS_RESERVED_BITS);
pub(crate) const STATUS_RESERVED_BITS_FIELD: Field = Field::new(STATUS_RESERVED_BITS);

/// Mask for parsing the broadcast received flag of a status word.
pub const STATUS_BROADCAST_RECEIVED: u16 = 0b0000000000010000;
pub(crate) const STATUS_BROADCAST_RECEIVED: u16 = 0b0000000000010000;

/// Field definition for the broadcast received flag of a status word.
pub const STATUS_BROADCAST_RECEIVED_FIELD: Field = Field::new(STATUS_BROADCAST_RECEIVED);
pub(crate) const STATUS_BROADCAST_RECEIVED_FIELD: Field = Field::new(STATUS_BROADCAST_RECEIVED);

/// Mask for parsing the busy flag of the status word.
pub const STATUS_TERMINAL_BUSY: u16 = 0b0000000000001000;
pub(crate) const STATUS_TERMINAL_BUSY: u16 = 0b0000000000001000;

/// Field definition for the busy flag of the status word.
pub const STATUS_TERMINAL_BUSY_FIELD: Field = Field::new(STATUS_TERMINAL_BUSY);
pub(crate) const STATUS_TERMINAL_BUSY_FIELD: Field = Field::new(STATUS_TERMINAL_BUSY);

/// Mask for parsing the subsystem flag of the status word.
pub const STATUS_SUBSYSTEM_FLAG: u16 = 0b0000000000000100;
pub(crate) const STATUS_SUBSYSTEM_FLAG: u16 = 0b0000000000000100;

/// Field definition for the subsystem flag of the status word.
pub const STATUS_SUBSYSTEM_FLAG_FIELD: Field = Field::new(STATUS_SUBSYSTEM_FLAG);
pub(crate) const STATUS_SUBSYSTEM_FLAG_FIELD: Field = Field::new(STATUS_SUBSYSTEM_FLAG);

/// Mask for parsing the bus control accept flag of the status word.
pub const STATUS_DYNAMIC_BUS_ACCEPT: u16 = 0b0000000000000010;
pub(crate) const STATUS_DYNAMIC_BUS_ACCEPT: u16 = 0b0000000000000010;

/// Field definition for the bus control accept flag of the status word.
pub const STATUS_DYNAMIC_BUS_ACCEPT_FIELD: Field = Field::new(STATUS_DYNAMIC_BUS_ACCEPT);
pub(crate) const STATUS_DYNAMIC_BUS_ACCEPT_FIELD: Field = Field::new(STATUS_DYNAMIC_BUS_ACCEPT);

/// Mask for parsing the terminal flag of the status word.
pub const STATUS_TERMINAL_FLAG: u16 = 0b0000000000000001;
pub(crate) const STATUS_TERMINAL_FLAG: u16 = 0b0000000000000001;

/// Field definition for the terminal flag of the status word.
pub const STATUS_TERMINAL_FLAG_FIELD: Field = Field::new(STATUS_TERMINAL_FLAG);
pub(crate) const STATUS_TERMINAL_FLAG_FIELD: Field = Field::new(STATUS_TERMINAL_FLAG);
59 changes: 48 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,57 @@
// #![no_std]
#![deny(clippy::unwrap_used)]
#![no_std]
#![forbid(
arithmetic_overflow,
absolute_paths_not_starting_with_crate,
box_pointers,
elided_lifetimes_in_paths,
explicit_outlives_requirements,
ffi_unwind_calls,
keyword_idents,
let_underscore_drop,
macro_use_extern_crate,
meta_variable_misuse,
missing_abi,
missing_copy_implementations,
missing_debug_implementations,
missing_docs,
non_ascii_idents,
rust_2021_incompatible_closure_captures,
rust_2021_incompatible_or_patterns,
rust_2021_prefixes_incompatible_syntax,
rust_2021_prelude_collisions,
single_use_lifetimes,
trivial_casts,
trivial_numeric_casts,
unreachable_pub,
unsafe_code,
unsafe_op_in_unsafe_fn,
unstable_features,
unused_crate_dependencies,
unused_extern_crates,
unused_import_braces,
unused_lifetimes,
unused_macro_rules,
unused_qualifications,
// unused_results,
unused_tuple_struct_fields,
variant_size_differences
)]
#![doc = include_str!("../README.md")]

pub mod errors;
pub mod fields;
pub mod flags;
pub mod message;
pub mod word;
mod errors;
mod flags;
mod message;
mod word;

pub use message::{Message, Packet};
pub(crate) mod fields;

pub use errors::{Error, Result};
pub use crate::message::{Message, MessageDirection, MessageSide, MessageType, Packet};

pub use word::{CommandWord, DataWord, StatusWord};
pub use crate::errors::{Error, MessageError, Result, SubsystemError, SystemError, TerminalError};

pub use flags::{
pub use crate::word::{CommandWord, DataWord, StatusWord, WordType};

pub use crate::flags::{
Address, BroadcastCommand, BusControlAccept, Instrumentation, ModeCode, Reserved,
ServiceRequest, SubAddress, TerminalBusy, TransmitReceive,
};
Loading