196 lines
6.4 KiB
C++
196 lines
6.4 KiB
C++
/*
|
|
* CircularBinaryRemoteBuffer.cpp
|
|
*
|
|
* Created on: 24 àïð. 2020 ã.
|
|
* Author: LeonidTitov
|
|
*/
|
|
|
|
#include "CircularBinaryRemoteBuffer.hh"
|
|
#include <cstring>
|
|
#include <algorithm>
|
|
|
|
std::size_t driver::CircularBinaryRemoteBuffer::get_frame_size() const {
|
|
|
|
return frame_size;
|
|
|
|
}
|
|
|
|
|
|
bool driver::CircularBinaryRemoteBuffer::put( const char * frame ) {
|
|
|
|
if( memory.isWriteComplete() ) {
|
|
if( put_cache_writed == put_cache_stored ) {
|
|
|
|
std::size_t grow_up = ( put_cache_writed - put_cache_begin ) / frame_size;
|
|
|
|
index_in_memory = wrap_index( index_in_memory + grow_up );
|
|
|
|
put_cache_writed = put_cache_stored = put_cache_begin;
|
|
}
|
|
}
|
|
|
|
if( put_cache_stored + frame_size <= put_cache_end ) {
|
|
|
|
index = wrap_index( index + 1 );
|
|
loaded_frames = loaded_frames + 1 < number_of_frames ? loaded_frames + 1 : number_of_frames;
|
|
|
|
std::memcpy( put_cache_stored, frame, frame_size );
|
|
put_cache_stored += frame_size;
|
|
|
|
} else return false;
|
|
|
|
std::size_t part_size = cut_part( put_cache_stored - put_cache_writed );
|
|
|
|
if( memory.write( put_cache_writed, position_in_memory, part_size ) ) {
|
|
|
|
put_cache_writed += part_size;
|
|
position_in_memory = wrap_position( position_in_memory + part_size );
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void driver::CircularBinaryRemoteBuffer::clear() {
|
|
|
|
std::size_t current_index = index;
|
|
|
|
//todo: Áåçîïàñíûé ñáðîñ.
|
|
do {
|
|
|
|
index_in_memory = 0;
|
|
put_cache_writed = put_cache_stored = put_cache_begin;
|
|
|
|
index = 0;
|
|
loaded_frames = 0;
|
|
position_in_memory = 0;
|
|
|
|
cached_index_begin = 0;
|
|
cached_index_end = 0;
|
|
|
|
} while( current_index != index );
|
|
|
|
}
|
|
|
|
std::pair<driver::CircularBinaryRemoteBuffer::Index, std::size_t> driver::CircularBinaryRemoteBuffer::fixate( std::size_t desired_pretrigger_frames ) {
|
|
|
|
std::size_t current_index = index;
|
|
std::size_t pretrigger_frames = desired_pretrigger_frames < loaded_frames ? desired_pretrigger_frames : loaded_frames;
|
|
loaded_frames = pretrigger_frames;
|
|
|
|
return { Index( current_index < pretrigger_frames ? number_of_frames - pretrigger_frames + current_index : current_index - pretrigger_frames, number_of_frames ),
|
|
pretrigger_frames };
|
|
|
|
}
|
|
|
|
driver::CircularBinaryRemoteBuffer::CircularBinaryRemoteBuffer(
|
|
peripheral::IMemoryAccess & memory, std::size_t frame_size,
|
|
char * put_cache, std::size_t put_cache_size,
|
|
char * get_cache, std::size_t get_cache_size ) :
|
|
memory(memory), frame_size(frame_size),
|
|
put_cache_begin(put_cache), put_cache_end(put_cache + put_cache_size), put_cache_stored(put_cache), put_cache_writed(put_cache),
|
|
get_cache_begin(get_cache), get_cache_capacity( get_cache_size / frame_size ),
|
|
index(0), index_in_memory(0), loaded_frames(0), position_in_memory(0), number_of_frames(memory.getCapacity() / frame_size), useful_capacity((memory.getCapacity() / frame_size)*frame_size),
|
|
cached_index_begin(0), cached_index_end(0) {}
|
|
|
|
std::size_t driver::CircularBinaryRemoteBuffer::wrap_index(
|
|
std::size_t next_index ) {
|
|
|
|
return next_index < number_of_frames ? next_index : next_index - number_of_frames;
|
|
|
|
}
|
|
|
|
std::size_t driver::CircularBinaryRemoteBuffer::wrap_position(
|
|
std::size_t next_position ) {
|
|
|
|
return next_position < useful_capacity ? next_position : next_position - useful_capacity;
|
|
|
|
}
|
|
|
|
void driver::CircularBinaryRemoteBuffer::restart( const Index & frame_index ) {
|
|
//todo:
|
|
|
|
}
|
|
|
|
std::size_t driver::CircularBinaryRemoteBuffer::fixed( const Index & frame_index ) const {
|
|
|
|
std::size_t current_index = index;
|
|
|
|
std::size_t temp = ( current_index < frame_index.position ?
|
|
number_of_frames - frame_index.position + current_index :
|
|
current_index - frame_index.position );
|
|
|
|
return temp > loaded_frames ? 0 : temp;
|
|
|
|
}
|
|
|
|
std::size_t driver::CircularBinaryRemoteBuffer::available_in_memory(
|
|
const Index & frame_index ) {
|
|
|
|
std::size_t temp = ( index_in_memory < frame_index.position ?
|
|
number_of_frames - frame_index.position + index_in_memory :
|
|
index_in_memory - frame_index.position );
|
|
|
|
return temp > loaded_frames ? 0 : temp;
|
|
|
|
}
|
|
|
|
const char * driver::CircularBinaryRemoteBuffer::get( const Index & frame_index ) {
|
|
|
|
if( not fixed( frame_index ) )
|
|
return nullptr;
|
|
|
|
if( cached_index_begin <= frame_index.position and frame_index.position < cached_index_end )
|
|
return get_cache_begin + frame_size * ( frame_index.position - cached_index_begin );
|
|
|
|
std::size_t current_index = index;
|
|
|
|
std::size_t load_from_memory = std::min( available_in_memory( frame_index ), get_cache_capacity );
|
|
std::size_t available_frames = std::min( fixed( frame_index ), get_cache_capacity );
|
|
std::size_t load_from_cache = available_frames - load_from_memory;
|
|
|
|
if( load_from_memory < get_cache_capacity ) do {
|
|
|
|
current_index = index;
|
|
|
|
load_from_memory = std::min( available_in_memory( frame_index ), get_cache_capacity );
|
|
available_frames = std::min( fixed( frame_index ), get_cache_capacity );
|
|
load_from_cache = available_frames - load_from_memory;
|
|
|
|
std::memcpy( get_cache_begin + load_from_memory * frame_size, put_cache_begin, load_from_cache * frame_size );
|
|
|
|
} while( current_index != index );
|
|
|
|
std::size_t first_part = ( load_from_memory * frame_size + frame_index.position * frame_size ) < useful_capacity ? load_from_memory * frame_size : useful_capacity - frame_index.position * frame_size; //cut_part( load_from_memory * frame_size );
|
|
std::size_t second_part = load_from_memory * frame_size - first_part;
|
|
|
|
if( first_part ) {
|
|
while( not memory.read( get_cache_begin, frame_index.position * frame_size, first_part ) );
|
|
while( not memory.isReadComplete() );
|
|
}
|
|
|
|
if( second_part ) {
|
|
//todo: wrap position?
|
|
while( not memory.read( get_cache_begin + first_part, 0, second_part ) );
|
|
while( not memory.isReadComplete() );
|
|
}
|
|
|
|
cached_index_begin = frame_index.position;
|
|
cached_index_end = frame_index.position + available_frames;
|
|
|
|
return get( frame_index );
|
|
|
|
}
|
|
|
|
std::size_t driver::CircularBinaryRemoteBuffer::capacity() const {
|
|
|
|
return number_of_frames;
|
|
|
|
}
|
|
|
|
std::size_t driver::CircularBinaryRemoteBuffer::cut_part( std::size_t next_part ) {
|
|
|
|
return ( next_part + position_in_memory ) < useful_capacity ? next_part : useful_capacity - position_in_memory;
|
|
|
|
}
|