MotorControlModuleSDFM_TMS3.../Projects/EFC_Application/UMLibrary/driver/CircularBinaryRemoteBuffer.cpp

196 lines
6.4 KiB
C++
Raw Normal View History

/*
* CircularBinaryRemoteBuffer.cpp
*
* Created on: 24 <EFBFBD><EFBFBD><EFBFBD>. 2020 <EFBFBD>.
* 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: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>.
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;
}