Prusa MINI Firmware overview
BinaryStream Class Reference

#include <binary_protocol.h>

Collaboration diagram for BinaryStream:

Classes

struct  Packet
 

Public Types

enum  Protocol : uint8_t { Protocol::CONTROL, Protocol::FILE_TRANSFER }
 
enum  ProtocolControl : uint8_t { ProtocolControl::SYNC = 1, ProtocolControl::CLOSE }
 
enum  StreamState : uint8_t {
  StreamState::PACKET_RESET, StreamState::PACKET_WAIT, StreamState::PACKET_HEADER, StreamState::PACKET_DATA,
  StreamState::PACKET_FOOTER, StreamState::PACKET_PROCESS, StreamState::PACKET_RESEND, StreamState::PACKET_TIMEOUT,
  StreamState::PACKET_ERROR
}
 

Public Member Functions

void reset ()
 
uint32_t checksum (uint32_t cs, uint8_t value)
 
bool stream_read (uint8_t &data)
 
template<const size_t buffer_size>
void receive (char(&buffer)[buffer_size])
 
void dispatch ()
 
void idle ()
 

Public Attributes

struct BinaryStream::Packet packet
 
uint8_t packet_retries
 
uint8_t sync
 
uint16_t buffer_next_index
 
uint32_t bytes_received
 
StreamState stream_state = StreamState::PACKET_RESET
 

Static Public Attributes

static const uint16_t PACKET_MAX_WAIT = 500
 
static const uint16_t RX_TIMESLICE = 20
 
static const uint16_t MAX_RETRIES = 0
 
static const uint16_t VERSION_MAJOR = 0
 
static const uint16_t VERSION_MINOR = 1
 
static const uint16_t VERSION_PATCH = 0
 

Member Enumeration Documentation

◆ Protocol

Enumerator
CONTROL 
FILE_TRANSFER 
223 : uint8_t { CONTROL, FILE_TRANSFER };

◆ ProtocolControl

Enumerator
SYNC 
CLOSE 
225 : uint8_t { SYNC = 1, CLOSE };

◆ StreamState

Enumerator
PACKET_RESET 
PACKET_WAIT 
PACKET_HEADER 
PACKET_DATA 
PACKET_FOOTER 
PACKET_PROCESS 
PACKET_RESEND 
PACKET_TIMEOUT 
PACKET_ERROR 
227  : uint8_t { PACKET_RESET, PACKET_WAIT, PACKET_HEADER, PACKET_DATA, PACKET_FOOTER,
228  PACKET_PROCESS, PACKET_RESEND, PACKET_TIMEOUT, PACKET_ERROR };

Member Function Documentation

◆ reset()

void BinaryStream::reset ( )
274  {
275  sync = 0;
276  packet_retries = 0;
277  buffer_next_index = 0;
278  }
Here is the caller graph for this function:

◆ checksum()

uint32_t BinaryStream::checksum ( uint32_t  cs,
uint8_t  value 
)
281  {
282  uint16_t cs_low = (((cs & 0xFF) + value) % 255);
283  return ((((cs >> 8) + cs_low) % 255) << 8) | cs_low;
284  }
Here is the caller graph for this function:

◆ stream_read()

bool BinaryStream::stream_read ( uint8_t data)
289  {
292  return false;
293  }
294  if (!bs_serial_data_available(card.transfer_port_index)) return false;
295  data = bs_read_serial(card.transfer_port_index);
297  return true;
298  }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ receive()

template<const size_t buffer_size>
void BinaryStream::receive ( char(&)  buffer[buffer_size])

Data stream packet handling

301  {
302  uint8_t data = 0;
303  millis_t transfer_window = millis() + RX_TIMESLICE;
304 
305  #if ENABLED(SDSUPPORT)
306  PORT_REDIRECT(card.transfer_port_index);
307  #endif
308 
309  #pragma GCC diagnostic push
310  #pragma GCC diagnostic ignored "-Warray-bounds"
311 
312  while (PENDING(millis(), transfer_window)) {
313  switch (stream_state) {
314  /**
315  * Data stream packet handling
316  */
318  packet.reset();
321  if (!stream_read(data)) { idle(); return; } // no active packet so don't wait
322  packet.header.data[1] = data;
326  }
327  else {
328  // stream corruption drop data
329  packet.header.data[0] = data;
330  }
331  break;
333  if (!stream_read(data)) break;
334 
337 
338  // header checksum calculation can't contain the checksum
339  if (packet.bytes_received == sizeof(Packet::header) - 2)
341 
342  if (packet.bytes_received == sizeof(Packet::header)) {
344  // The SYNC control packet is a special case in that it doesn't require the stream sync to be correct
345  if (static_cast<Protocol>(packet.header.protocol()) == Protocol::CONTROL && static_cast<ProtocolControl>(packet.header.type()) == ProtocolControl::SYNC) {
346  SERIAL_ECHOLNPAIR("ss", sync, ",", buffer_size, ",", VERSION_MAJOR, ".", VERSION_MINOR, ".", VERSION_PATCH);
348  break;
349  }
350  if (packet.header.sync == sync) {
351  buffer_next_index = 0;
353  if (packet.header.size) {
355  packet.buffer = static_cast<char *>(&buffer[0]); // multipacket buffering not implemented, always allocate whole buffer to packet
356  }
357  else
359  }
360  else if (packet.header.sync == sync - 1) { // ok response must have been lost
361  SERIAL_ECHOLNPAIR("ok", packet.header.sync); // transmit valid packet received and drop the payload
363  }
364  else if (packet_retries) {
365  stream_state = StreamState::PACKET_RESET; // could be packets already buffered on flow controlled connections, drop them without ack
366  }
367  else {
368  SERIAL_ECHO_MSG("Datastream packet out of order");
370  }
371  }
372  else {
374  SERIAL_ECHOLNPAIR("Packet header(", packet.header.sync, "?) corrupt");
376  }
377  }
378  break;
380  if (!stream_read(data)) break;
381 
382  if (buffer_next_index < buffer_size)
384  else {
385  SERIAL_ECHO_MSG("Datastream packet data buffer overrun");
387  break;
388  }
389 
393 
397  }
398  break;
400  if (!stream_read(data)) break;
401 
403  if (packet.bytes_received == sizeof(Packet::footer)) {
406  }
407  else {
409  SERIAL_ECHOLNPAIR("Packet(", packet.header.sync, ") payload corrupt");
411  }
412  }
413  break;
415  sync++;
416  packet_retries = 0;
418 
419  SERIAL_ECHOLNPAIR("ok", packet.header.sync); // transmit valid packet received
420  dispatch();
422  break;
424  if (packet_retries < MAX_RETRIES || MAX_RETRIES == 0) {
425  packet_retries++;
428  SERIAL_ECHOLNPAIR("Resend request ", int(packet_retries));
429  SERIAL_ECHOLNPAIR("rs", sync);
430  }
431  else
433  break;
435  SERIAL_ECHO_MSG("Datastream timeout");
437  break;
440  reset(); // reset everything, resync required
442  break;
443  }
444  }
445 
446  #pragma GCC diagnostic pop
447  }
Here is the call graph for this function:

◆ dispatch()

void BinaryStream::dispatch ( )
449  {
450  switch(static_cast<Protocol>(packet.header.protocol())) {
451  case Protocol::CONTROL:
452  switch(static_cast<ProtocolControl>(packet.header.type())) {
453  case ProtocolControl::CLOSE: // revert back to ASCII mode
454  card.flag.binary_mode = false;
455  break;
456  default:
457  SERIAL_ECHO_MSG("Unknown BinaryProtocolControl Packet");
458  }
459  break;
461  SDFileTransferProtocol::process(packet.header.type(), packet.buffer, packet.header.size); // send user data to be processed
462  break;
463  default:
464  SERIAL_ECHO_MSG("Unsupported Binary Protocol");
465  }
466  }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ idle()

void BinaryStream::idle ( )
468  {
469  // Some Protocols may need periodic updates without new data
471  }
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ packet

struct BinaryStream::Packet BinaryStream::packet

◆ PACKET_MAX_WAIT

const uint16_t BinaryStream::PACKET_MAX_WAIT = 500
static

◆ RX_TIMESLICE

const uint16_t BinaryStream::RX_TIMESLICE = 20
static

◆ MAX_RETRIES

const uint16_t BinaryStream::MAX_RETRIES = 0
static

◆ VERSION_MAJOR

const uint16_t BinaryStream::VERSION_MAJOR = 0
static

◆ VERSION_MINOR

const uint16_t BinaryStream::VERSION_MINOR = 1
static

◆ VERSION_PATCH

const uint16_t BinaryStream::VERSION_PATCH = 0
static

◆ packet_retries

uint8_t BinaryStream::packet_retries

◆ sync

uint8_t BinaryStream::sync

◆ buffer_next_index

uint16_t BinaryStream::buffer_next_index

◆ bytes_received

uint32_t BinaryStream::bytes_received

◆ stream_state

StreamState BinaryStream::stream_state = StreamState::PACKET_RESET
PENDING
#define PENDING(NOW, SOON)
Definition: millis_t.h:28
PORT_REDIRECT
#define PORT_REDIRECT(p)
Definition: serial.h:66
BinaryStream::Packet::header
Header header
Definition: binary_protocol.h:256
BinaryStream::StreamState::PACKET_DATA
bs_read_serial
int bs_read_serial(const uint8_t index)
Definition: binary_protocol.h:42
BinaryStream::reset
void reset()
Definition: binary_protocol.h:274
BinaryStream::Packet::header_checksum
uint16_t header_checksum
Definition: binary_protocol.h:259
BinaryStream::Packet::Header::size
uint16_t size
Definition: binary_protocol.h:239
BinaryStream::StreamState::PACKET_HEADER
BinaryStream::StreamState::PACKET_RESEND
BinaryStream::Protocol::FILE_TRANSFER
BinaryStream::Packet::Header::HEADER_TOKEN
static constexpr uint16_t HEADER_TOKEN
Definition: binary_protocol.h:233
BinaryStream::packet_retries
uint8_t packet_retries
Definition: binary_protocol.h:474
SYNC
Definition: inflate.h:52
BinaryStream::ProtocolControl::SYNC
data
uint8_t data[8]
Definition: masstorage.h:49
BinaryStream::VERSION_MAJOR
static const uint16_t VERSION_MAJOR
Definition: binary_protocol.h:473
BinaryStream::PACKET_MAX_WAIT
static const uint16_t PACKET_MAX_WAIT
Definition: binary_protocol.h:473
BinaryStream::sync
uint8_t sync
Definition: binary_protocol.h:474
BinaryStream::StreamState::PACKET_PROCESS
BinaryStream::stream_read
bool stream_read(uint8_t &data)
Definition: binary_protocol.h:289
millis
uint32_t millis(void)
Definition: wiring_time.c:29
BinaryStream::Packet::reset
void reset()
Definition: binary_protocol.h:263
BinaryStream::Packet::Header::protocol
uint8_t protocol()
Definition: binary_protocol.h:242
SDFileTransferProtocol::idle
static void idle()
Definition: binary_protocol.h:157
SERIAL_ECHO_START
#define SERIAL_ECHO_START()
Definition: serial.h:179
BinaryStream::VERSION_MINOR
static const uint16_t VERSION_MINOR
Definition: binary_protocol.h:473
SDFileTransferProtocol::process
static void process(uint8_t packet_type, char *buffer, const uint16_t length)
Definition: binary_protocol.h:166
BinaryStream::buffer_next_index
uint16_t buffer_next_index
Definition: binary_protocol.h:475
BinaryStream::StreamState::PACKET_FOOTER
BinaryStream::StreamState::PACKET_ERROR
BinaryStream::checksum
uint32_t checksum(uint32_t cs, uint8_t value)
Definition: binary_protocol.h:281
SERIAL_ECHO_MSG
#define SERIAL_ECHO_MSG(S)
Definition: serial.h:183
BinaryStream::packet
struct BinaryStream::Packet packet
BinaryStream::Packet::Header::checksum
uint16_t checksum
Definition: binary_protocol.h:240
BinaryStream::stream_state
StreamState stream_state
Definition: binary_protocol.h:477
BinaryStream::Packet::bytes_received
uint32_t bytes_received
Definition: binary_protocol.h:258
BinaryStream::Packet::footer
Footer footer
Definition: binary_protocol.h:257
BinaryStream::Packet::Header::data
uint8_t data[1]
Definition: binary_protocol.h:245
SERIAL_ECHOLNPAIR
#define SERIAL_ECHOLNPAIR(V...)
Definition: serial.h:144
BinaryStream::StreamState::PACKET_RESET
BinaryStream::VERSION_PATCH
static const uint16_t VERSION_PATCH
Definition: binary_protocol.h:473
ELAPSED
#define ELAPSED(NOW, SOON)
Definition: millis_t.h:29
uint8_t
const uint8_t[]
Definition: 404_html.c:3
BinaryStream::StreamState::PACKET_WAIT
BinaryStream::Packet::Header::token
uint16_t token
Definition: binary_protocol.h:235
BinaryStream::Packet::Header::sync
uint8_t sync
Definition: binary_protocol.h:236
BinaryStream::Packet::checksum
uint16_t checksum
Definition: binary_protocol.h:259
BinaryStream::Packet::timeout
millis_t timeout
Definition: binary_protocol.h:260
BinaryStream::dispatch
void dispatch()
Definition: binary_protocol.h:449
BinaryStream::Protocol::CONTROL
BinaryStream::StreamState::PACKET_TIMEOUT
BinaryStream::Packet::buffer
char * buffer
Definition: binary_protocol.h:261
BinaryStream::ProtocolControl::CLOSE
BinaryStream::Packet::Header::type
uint8_t type()
Definition: binary_protocol.h:243
millis_t
uint32_t millis_t
Definition: millis_t.h:26
BinaryStream::MAX_RETRIES
static const uint16_t MAX_RETRIES
Definition: binary_protocol.h:473
bs_serial_data_available
bool bs_serial_data_available(const uint8_t index)
Definition: binary_protocol.h:32
BinaryStream::idle
void idle()
Definition: binary_protocol.h:468
BinaryStream::bytes_received
uint32_t bytes_received
Definition: binary_protocol.h:476
BinaryStream::RX_TIMESLICE
static const uint16_t RX_TIMESLICE
Definition: binary_protocol.h:473