pub struct Packet<const T: usize> { /* private fields */ }Implementations§
Source§impl<const T: usize> Packet<T>
impl<const T: usize> Packet<T>
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a new Packet with a data buffer of const T: usize bytes
§Example
pub fn main() {
let rx = flem::Packet::<100>::new(); // Create new packet that can send / receive up to 100 bytes per packet
}Sourcepub fn pack_data(&mut self, request: u16, data: &[u8]) -> Result<(), Status>
pub fn pack_data(&mut self, request: u16, data: &[u8]) -> Result<(), Status>
Convenience function to response with data. The response byte is automatically set to SUCCESS.
Sourcepub fn pack_error(
&mut self,
request: u16,
error: u16,
data: &[u8],
) -> Result<(), Status>
pub fn pack_error( &mut self, request: u16, error: u16, data: &[u8], ) -> Result<(), Status>
Convenience function to respond quickly if an error occurs (without data).
Sourcepub fn pack_id(&mut self, id: &DataId, ascii: bool) -> Result<(), Status>
pub fn pack_id(&mut self, id: &DataId, ascii: bool) -> Result<(), Status>
Convenience function to respond with the ID. If communicating with UTF-8 partners, ascii should be true. This can only be used if the data packets are 30 bytes or longer (or twice that if ascii = false).
§Arguments
ascii- Packages the ID as a UTF-8 ID. Used when talking to C/C++ partners.
Sourcepub fn pack(&mut self)
pub fn pack(&mut self)
Pack a packet up: adds header and computes checksum.
§Example
pub fn main() {
use flem::{Packet};
const PACKET_SIZE: usize = 64; // 64 byte packet
const FLEM_EXAMPLE_REQUEST: u16 = 0xF;
let mut rx = Packet::<PACKET_SIZE>::new();
let mut data = [0 as u8; PACKET_SIZE];
/* Add data as needed to the data buffer */
rx.add_data(&data);
rx.set_request(FLEM_EXAMPLE_REQUEST);
assert_ne!(rx.get_header(), 0x5555, "Packet header hasn't been set, should NOT be 0x5555");
rx.pack();
assert_eq!(rx.get_header(), 0x5555, "Packet header has been set, should be 0x5555");
/* Send data */
}Sourcepub fn get_data(&self) -> [u8; T]
pub fn get_data(&self) -> [u8; T]
Returns a copy of the data part of the packet as a byte array
Sourcepub fn add_data(&mut self, data: &[u8]) -> Result<(), Status>
pub fn add_data(&mut self, data: &[u8]) -> Result<(), Status>
Adds data to a packet if there is room.
Sourcepub fn validate(&mut self) -> bool
pub fn validate(&mut self) -> bool
Computes the Checksum on the packet and compares to the sent checksum. Returns true if there is a match, otherwise false.
Sourcepub fn construct(&mut self, byte: u8) -> Result<(), Status>
pub fn construct(&mut self, byte: u8) -> Result<(), Status>
Construct a packet one byte at a time. An internal counter keeps track of where the byte should go. The current return value is the Status and should be one of the following:
- HeaderBytesNotFound - The packet header was not found
- ChecksumError - The computed checksum does not match the sent checksum
- PacketOverflow - Data is being added beyond length of the packet
- PacketBuilding - This should be the default most of the time and indicates the packet is being built without issues so far.
- PacketReceived - All data bytes have been received and the checksum has been validated
§Arguments
byte- A single byte to add to a packet.
§Example
pub fn main() {
use flem::{Packet};
const PACKET_SIZE: usize = 64; // 64 byte packet
const FLEM_EXAMPLE_REQUEST: u16 = 0xF;
let mut rx = Packet::<PACKET_SIZE>::new();
let mut tx = Packet::<PACKET_SIZE>::new();
let mut data = [0 as u8; PACKET_SIZE];
/* Add data as needed to the data buffer */
tx.add_data(&data);
tx.set_request(FLEM_EXAMPLE_REQUEST);
tx.pack();
/* Send data */
let tx_as_u8_array = tx.bytes();
// We are sending bytes across a hardware bus
let mut packet_received = false;
for byte in tx_as_u8_array {
// The received is getting bytes on the hardware bus
match rx.construct(*byte) {
Ok(_) => {
packet_received = true;
},
Err(status) => {
/* Handle other cases here */
}
}
}
assert!(packet_received, "Packet should have been constructed and validated.");
}Sourcepub fn get_byte(&mut self) -> Result<u8, Status>
pub fn get_byte(&mut self) -> Result<u8, Status>
This function treats the entire packet as a byte array and uses internal counters to determine the next byte. Keep calling this until either an error occurs or status is Status::GetByteFinished.
It is often easier to use .bytes(), but this function is meant to be used in an async nature, for example an interrupt driven UART transmit FIFO.
The return value is a Result composed of the byte requested if everything is going well, or a Status as an Error indicating all bytes have been gotten.
§Example
pub fn main() {
use flem::{Packet};
use heapless;
const PACKET_SIZE: usize = 64; // 64 byte packet
const FLEM_EXAMPLE_REQUEST: u16 = 0xF;
let mut rx = Packet::<PACKET_SIZE>::new();
let mut tx = Packet::<PACKET_SIZE>::new();
let mut data = [0 as u8; PACKET_SIZE];
/* Add data as needed to the data buffer */
tx.add_data(&data);
tx.set_request(FLEM_EXAMPLE_REQUEST);
tx.pack();
/* Send data */
let mut tx_fifo_queue = heapless::spsc::Queue::<u8, 8>::new();
let mut keep_sending = true;
let mut packet_received = false;
let mut status = flem::Status::Ok;
while keep_sending {
if !tx_fifo_queue.is_full() && status != flem::Status::GetByteFinished {
match tx.get_byte() {
Ok(byte) => {
tx_fifo_queue.enqueue(byte).unwrap();
},
Err(x) => {
/* Tx code should stop transmitting */
status = x;
}
}
}else{
// Queue is full, Tx the data, Rx on the other end
while !tx_fifo_queue.is_empty() {
match rx.construct(tx_fifo_queue.dequeue().unwrap()) {
Ok(_) => {
packet_received = true;
keep_sending = false;
},
Err(status) => {
/* Catch other statuses here on the Rx side */
}
}
}
}
}
assert!(packet_received, "Packet should have been transferred");
// This test is redundant, since the checksums passed, still nice to see
let rx_bytes = rx.bytes();
let tx_bytes = tx.bytes();
for i in 0..rx_bytes.len() {
assert_eq!(rx_bytes[i], tx_bytes[i], "Rx and Tx packets don't match");
}
}Sourcepub fn set_request(&mut self, request: u16)
pub fn set_request(&mut self, request: u16)
Sets the Flem request field
Sourcepub fn get_request(&self) -> u16
pub fn get_request(&self) -> u16
Gets the Flem request field
Sourcepub fn get_checksum(&self) -> u16
pub fn get_checksum(&self) -> u16
Returns the stored checksum value
Sourcepub fn set_response(&mut self, response: u16)
pub fn set_response(&mut self, response: u16)
Sets the Flem response field
Sourcepub fn get_response(&self) -> u16
pub fn get_response(&self) -> u16
Gets the Flem response field
Sourcepub fn get_status(&mut self) -> Status
pub fn get_status(&mut self) -> Status
Gets the status byte from the packet
Sourcepub fn get_header(&self) -> u16
pub fn get_header(&self) -> u16
Get the header byte as u16
pub fn get_data_length(&self) -> usize
Sourcepub fn checksum(&mut self, store: bool) -> u16
pub fn checksum(&mut self, store: bool) -> u16
Computes a CRC16 IBM style checksum on the packet, except the header and checksum bytes
Sourcepub fn reset_lazy(&mut self)
pub fn reset_lazy(&mut self)
Resets the packet to all 0’s, but does not clear the data array. Much faster than zeroing out the packet’s data buffer. Packets should be cleared before reusing, both Rx and Tx.
Sourcepub fn reset(&mut self)
pub fn reset(&mut self)
Resets the packet. The data array is cleared only if clear_data is true. Packets should be cleared before reusing, both Rx and Tx.
§Arguments
clear_data- Zero out the data array.
Sourcepub fn length(&self) -> usize
pub fn length(&self) -> usize
Length of the packet, including the header and data.
§Example
pub fn main() {
const PACKET_SIZE: usize = 100;
let mut tx = flem::Packet::<PACKET_SIZE>::new();
assert_eq!(tx.length() as usize, flem::FLEM_HEADER_SIZE as usize, "Length should be only {} bytes for the header", flem::FLEM_HEADER_SIZE);
let data = [0 as u8; PACKET_SIZE];
tx.add_data(&data);
assert_eq!(tx.length() as usize, PACKET_SIZE + flem::FLEM_HEADER_SIZE as usize, "Length should be {} bytes (packet size) + {} bytes for the header", PACKET_SIZE, flem::FLEM_HEADER_SIZE);
}