MotorControlModuleSDFM_TMS3.../Projects/EFC_Communication/UMLibrary/driver/CircularBinaryRemoteBuffer.cpp
2024-06-07 11:12:56 +03:00

196 lines
6.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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;
}