1#ifndef BLUETOE_LINK_LAYER_LL_DAAT_BUFFER_HPP
2#define BLUETOE_LINK_LAYER_LL_DAAT_BUFFER_HPP
7#include <initializer_list>
10#include <bluetoe/default_pdu_layout.hpp>
11#include "ring_buffer.hpp"
36 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
55 static constexpr std::size_t
size = TransmitSize + ReceiveSize;
78 "TransmitSize should at least be large enough to store one L2CAP PDU plus overheader required by the hardware." );
81 "ReceiveSize should at least be large enough to store one L2CAP PDU plus overheader required by the hardware." );
125 return TransmitSize - ( layout::data_channel_pdu_memory_size( 0 ) - 2 );
302 std::uint8_t buffer_[
size ];
305 volatile std::size_t max_rx_size_;
308 volatile std::size_t max_tx_size_;
310 bool sequence_number_;
311 bool next_expected_sequence_number_;
312 uint8_t empty_[ layout::data_channel_pdu_memory_size( 0 ) ];
314 bool empty_sequence_number_;
316 static constexpr std::size_t ll_header_size = 2;
317 static constexpr std::uint8_t more_data_flag = 0x10;
318 static constexpr std::uint8_t sn_flag = 0x8;
319 static constexpr std::uint8_t nesn_flag = 0x4;
320 static constexpr std::uint8_t ll_empty_id = 0x01;
323 const std::uint8_t* transmit_buffer()
const
325 return &buffer_[ 0 ];
328 std::uint8_t* transmit_buffer()
330 return &buffer_[ 0 ];
333 const std::uint8_t* receive_buffer()
const
335 return &buffer_[ TransmitSize ];
338 std::uint8_t* receive_buffer()
340 return &buffer_[ TransmitSize ];
343 write_buffer set_next_expected_sequence_number( read_buffer )
const;
349 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
351 : receive_buffer_( receive_buffer() )
352 , transmit_buffer_( transmit_buffer() )
354 layout::header( empty_, 0 );
358 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
364 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
367 assert( max_size >= min_buffer_size );
368 assert( max_size <= max_buffer_size );
369 assert( max_size <= ReceiveSize - layout_overhead );
371 max_rx_size_ = max_size;
374 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
380 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
383 assert( max_size >= min_buffer_size );
384 assert( max_size <= max_buffer_size );
385 assert( max_size <= TransmitSize - layout_overhead );
387 max_tx_size_ = max_size;
390 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
393 max_rx_size_ = min_buffer_size;
394 receive_buffer_.reset( receive_buffer() );
396 max_tx_size_ = min_buffer_size;
397 transmit_buffer_.reset( transmit_buffer() );
399 sequence_number_ =
false;
400 next_expected_sequence_number_ =
false;
404 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
407 return &buffer_[ 0 ];
410 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
413 typename Radio::lock_guard lock;
415 return transmit_buffer_.alloc_front( transmit_buffer(), size );
418 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
421 static constexpr std::uint8_t header_rfu_mask = 0xe0;
422 static_cast< void >( header_rfu_mask );
425 std::uint16_t header = layout::header( pdu );
426 assert( ( header & header_rfu_mask ) == 0 );
428 typename Radio::lock_guard lock;
431 if ( sequence_number_ )
434 layout::header( pdu, header );
437 sequence_number_ = !sequence_number_;
439 transmit_buffer_.push_front( transmit_buffer(), pdu );
442 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
445 return transmit_buffer_.next_end().size != 0;
448 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
453 std::size_t header = layout::header( buf );
455 header = next_expected_sequence_number_
456 ? ( header | nesn_flag )
457 : ( header & ~nesn_flag );
459 layout::header( buf, header );
464 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
467 const read_buffer next = transmit_buffer_.next_end();
474 const std::uint16_t header = layout::header( next ) | more_data_flag;
475 layout::header( next, header );
478 return set_next_expected_sequence_number(
read_buffer{ &empty_[ 0 ],
sizeof( empty_ ) } );
480 else if ( next.
size == 0 )
483 const std::uint16_t header = sequence_number_
484 ? sn_flag + ll_empty_id
487 layout::header( empty_, header );
491 empty_sequence_number_ = sequence_number_;
492 sequence_number_ = !sequence_number_;
494 return set_next_expected_sequence_number(
read_buffer{ &empty_[ 0 ],
sizeof( empty_ ) } );
497 if ( transmit_buffer_.more_than_one() )
498 layout::header( next, layout::header( next ) | more_data_flag );
500 return set_next_expected_sequence_number( next );
503 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
508 if ( empty_sequence_number_ != nesn )
513 const read_buffer next = transmit_buffer_.next_end();
519 const std::uint16_t header = layout::header( next );
520 if (
static_cast< bool >( header & sn_flag ) != nesn )
522 transmit_buffer_.pop_end( transmit_buffer() );
523 static_cast< Radio*
>( this )->increment_transmit_packet_counter();
528 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
531 return allocate_transmit_buffer( max_tx_size_ + layout_overhead );
534 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
537 typename Radio::lock_guard lock;
542 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
545 typename Radio::lock_guard lock;
547 receive_buffer_.pop_end( receive_buffer() );
550 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
553 return receive_buffer_.alloc_front(
const_cast< std::uint8_t*
>( receive_buffer() ), layout::data_channel_pdu_memory_size( max_rx_size_ - ll_header_size ) );
556 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
559 const std::uint16_t header = layout::header( pdu );
562 if ( ( header & 0x3 ) != 0 )
564 acknowledge( header & nesn_flag );
567 if (
static_cast< bool >( header & sn_flag ) == next_expected_sequence_number_ )
569 next_expected_sequence_number_ = !next_expected_sequence_number_;
571 if ( ( header & 0xff00 ) != 0 )
573 receive_buffer_.push_front( receive_buffer(), pdu );
574 static_cast< Radio*
>( this )->increment_receive_packet_counter();
579 return next_transmit();
582 template < std::
size_t TransmitSize, std::
size_t ReceiveSize,
typename Radio >
585 const std::uint16_t header = layout::header( pdu );
588 if ( ( header & 0x3 ) != 0 )
590 acknowledge( header & nesn_flag );
593 if (
static_cast< bool >( header & sn_flag ) == next_expected_sequence_number_ )
595 next_expected_sequence_number_ = !next_expected_sequence_number_;
599 return next_transmit();
ring buffers for ingoing and outgoing LL Data PDUs
Definition: ll_data_pdu_buffer.hpp:38
read_buffer allocate_transmit_buffer(std::size_t size)
allocates a certain amount of memory to place a PDU to be transmitted .
Definition: ll_data_pdu_buffer.hpp:411
write_buffer acknowledge(read_buffer)
This function will be called, instead of received(), when the CRC of a received PDU is ok,...
Definition: ll_data_pdu_buffer.hpp:583
constexpr std::size_t max_max_rx_size() const
returns the maximum value that can be used as maximum receive size.
Definition: ll_data_pdu_buffer.hpp:93
void commit_transmit_buffer(read_buffer)
indicates that prior allocated memory is now ready for transmission
Definition: ll_data_pdu_buffer.hpp:419
write_buffer next_received() const
returns the oldest PDU out of the receive buffer.
Definition: ll_data_pdu_buffer.hpp:535
void stop_pdu_buffer()
places the buffer in stopped mode.
typename pdu_layout_by_radio< Radio >::pdu_layout layout
layout to be applied to each PDU.
Definition: ll_data_pdu_buffer.hpp:50
ll_data_pdu_buffer()
Definition: ll_data_pdu_buffer.hpp:350
void max_rx_size(std::size_t max_size)
set the maximum receive size
Definition: ll_data_pdu_buffer.hpp:365
static constexpr std::size_t layout_overhead
addition layout overhead introduced by the applied layout
Definition: ll_data_pdu_buffer.hpp:75
read_buffer allocate_receive_buffer() const
allocates a buffer for the next PDU to be received.
Definition: ll_data_pdu_buffer.hpp:551
static constexpr std::size_t header_size
16 bit header size of a link layer PDU
Definition: ll_data_pdu_buffer.hpp:70
bool pending_outgoing_data_available() const
returns true, if there is pending, outgoing data
Definition: ll_data_pdu_buffer.hpp:443
static constexpr std::size_t size
the size of memory in bytes that are return by raw()
Definition: ll_data_pdu_buffer.hpp:55
static constexpr std::size_t max_buffer_size
the maximum size an element in the buffer can have (header size + payload size).
Definition: ll_data_pdu_buffer.hpp:65
write_buffer next_transmit()
returns the next PDU to be transmitted
Definition: ll_data_pdu_buffer.hpp:465
void max_tx_size(std::size_t max_size)
set the maximum transmit size
Definition: ll_data_pdu_buffer.hpp:381
static constexpr std::size_t min_buffer_size
the minimum size an element in the buffer can have (header size + payload size).
Definition: ll_data_pdu_buffer.hpp:60
constexpr std::size_t max_max_tx_size() const
returns the maximum value that can be used as maximum receive size.
Definition: ll_data_pdu_buffer.hpp:123
write_buffer received(read_buffer)
This function will be called by the scheduled radio when a PDU was received without error.
Definition: ll_data_pdu_buffer.hpp:557
std::size_t max_rx_size() const
the current maximum receive size
Definition: ll_data_pdu_buffer.hpp:359
void reset_pdu_buffer()
places the buffer in running mode.
Definition: ll_data_pdu_buffer.hpp:391
std::uint8_t * raw_pdu_buffer()
returns the underlying raw buffer with a size of at least ll_data_pdu_buffer::size
Definition: ll_data_pdu_buffer.hpp:405
void free_received()
removes the oldest PDU from the receive buffer.
Definition: ll_data_pdu_buffer.hpp:543
read_buffer allocate_transmit_buffer()
calls allocate_transmit_buffer( max_tx_size() + layout_overhead );
Definition: ll_data_pdu_buffer.hpp:529
std::size_t max_tx_size() const
the current maximum transmit size
Definition: ll_data_pdu_buffer.hpp:375
structure, able to store variable sized link layer PDUs in a fixed size ring.
Definition: ring_buffer.hpp:28
implements a PDU layout, where in memory and over the air layout are equal.
Definition: default_pdu_layout.hpp:42
type suitable to store the location and size of a chunk of memory that can be used to receive from th...
Definition: buffer.hpp:18
std::size_t size
Definition: buffer.hpp:30
type suitable to store the location and size of a chunk of memory that can be used to transmit to the...
Definition: buffer.hpp:85