350 lines
7.5 KiB
C++
350 lines
7.5 KiB
C++
/*
|
||
* Scope.cpp
|
||
*
|
||
* Created on: 27 апр. 2020 г.
|
||
* Author: LeonidTitov
|
||
*/
|
||
|
||
#include "Scope.hh"
|
||
#include <algorithm>
|
||
|
||
bool driver::Scope::setup(Frame * new_frame, systemic::IValue<bool> * new_trigger,
|
||
TriggerMode mode, Times times_to_on, Time time_before,
|
||
Time time_after ) {
|
||
|
||
if( mode == Cyclic or mode == Repeat )
|
||
if( time_before != 0.0f )
|
||
return false;
|
||
|
||
if( not new_frame or not new_trigger )
|
||
return false;
|
||
|
||
trigger.stop();
|
||
capture.stop();
|
||
|
||
std::size_t frame_size = new_frame->size();
|
||
|
||
buffer_constructor.destroy( buffer );
|
||
buffer_constructor.construct( buffer, memory, frame_size, put_cache, put_cache_size, get_cache, get_cache_size );
|
||
|
||
frame = new_frame;
|
||
|
||
FrameIndex before_fix_frames, after_fix_frames;
|
||
FrameIndex step = 0;
|
||
|
||
do {
|
||
|
||
data_quant = ++step * process_quant;
|
||
|
||
before_fix_frames = time_before / ( data_quant );
|
||
after_fix_frames = time_after / ( data_quant );
|
||
|
||
} while( before_fix_frames + after_fix_frames > buffer->capacity() );
|
||
|
||
capture.setup( before_fix_frames, after_fix_frames, step );
|
||
trigger.setup(new_trigger, times_to_on, mode == Repeat );
|
||
restart_on_done = mode == Cyclic;
|
||
|
||
return is_setupped = true;
|
||
|
||
}
|
||
|
||
void driver::Scope::reset() {
|
||
|
||
disable();
|
||
|
||
buffer->clear();
|
||
|
||
is_setupped = false;
|
||
|
||
}
|
||
|
||
bool driver::Scope::isSetup() const {
|
||
|
||
return is_setupped;
|
||
|
||
}
|
||
|
||
void driver::Scope::start() {
|
||
|
||
trigger.start();
|
||
capture.start();
|
||
|
||
}
|
||
|
||
void driver::Scope::stop() {
|
||
|
||
trigger.stop();
|
||
|
||
}
|
||
|
||
void driver::Scope::disable() {
|
||
|
||
trigger.stop();
|
||
capture.stop();
|
||
|
||
}
|
||
|
||
std::pair<driver::Scope::Times, driver::Scope::Times> driver::Scope::trigger_progress() const {
|
||
|
||
return trigger.progress();
|
||
|
||
}
|
||
|
||
std::pair<driver::Scope::FrameIndex, driver::Scope::FrameIndex> driver::Scope::data_progress() const {
|
||
|
||
return capture.progress();
|
||
|
||
}
|
||
|
||
std::pair<driver::Scope::FrameIndex, driver::Scope::FrameIndex> driver::Scope::data_info() const {
|
||
|
||
return { buffer->fixed( capture.head() ), capture.trigger_position };
|
||
|
||
}
|
||
|
||
driver::Scope::Time driver::Scope::sample_time() const {
|
||
|
||
return data_quant;
|
||
|
||
}
|
||
|
||
bool driver::Scope::isActive() const {
|
||
|
||
return capture.is_active();
|
||
|
||
}
|
||
|
||
bool driver::Scope::isTriggerFixed() const {
|
||
|
||
return trigger.is_fixed();
|
||
|
||
}
|
||
|
||
std::pair<const char *, std::size_t> driver::Scope::getFrame(
|
||
FrameIndex index ) {
|
||
|
||
return { buffer->get( capture.head().relative(index) ), buffer->get_frame_size() };
|
||
|
||
}
|
||
|
||
void driver::Scope::freeFrame( FrameIndex index ) {}
|
||
|
||
driver::Scope::Scope(peripheral::IMemoryAccess & memory_access,
|
||
std::pmr::memory_resource * initialization, std::size_t put_cache_size, std::size_t get_cache_size ) :
|
||
frame( nullptr ), memory(memory_access), buffer_constructor( initialization ),
|
||
buffer( buffer_constructor.allocate(1) ),
|
||
put_cache( reinterpret_cast<char *>( initialization->allocate( put_cache_size, 1 ) ) ), put_cache_size(put_cache_size),
|
||
get_cache( reinterpret_cast<char *>( initialization->allocate( put_cache_size, 1 ) ) ), get_cache_size(get_cache_size),
|
||
process_quant( 0.0f ), data_quant( 0.0f ),
|
||
is_setupped( false ), restart_on_done( false ),
|
||
trigger(), capture() {}
|
||
|
||
void driver::Scope::setSampleTime( float ts_in_second ) {
|
||
|
||
process_quant = ts_in_second;
|
||
|
||
}
|
||
|
||
void driver::Scope::process() {
|
||
|
||
if( trigger.at_fix() )
|
||
capture.fix( buffer->fixate( capture.desired_trigger() ) );
|
||
|
||
if( capture.at_shot() )
|
||
buffer->put( frame->data() );
|
||
|
||
if( capture.is_done() ) {
|
||
|
||
if( restart_on_done ) {
|
||
|
||
buffer->restart( capture.head() );
|
||
|
||
trigger.start();
|
||
capture.start();
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
void driver::Scope::TriggerManager::setup( Condition * new_condition, Times new_threshold,
|
||
bool repeatable ) {
|
||
|
||
condition = new_condition;
|
||
prev_condition = *condition;
|
||
|
||
enable = false;
|
||
|
||
counter = 0;
|
||
threshold = new_threshold;
|
||
|
||
fixed = false;
|
||
repeat_mode = repeatable;
|
||
|
||
}
|
||
|
||
bool driver::Scope::TriggerManager::at_fix() {
|
||
|
||
bool fix = false;
|
||
|
||
bool current_condition = *condition;
|
||
|
||
if( current_condition and enable ) {
|
||
|
||
if( counter < threshold ) {
|
||
|
||
if( not prev_condition )
|
||
counter++;
|
||
|
||
} else if( not fixed ) {
|
||
|
||
counter = 0;
|
||
fixed = not repeat_mode;
|
||
|
||
fix = true;
|
||
|
||
}
|
||
}
|
||
|
||
prev_condition = current_condition;
|
||
|
||
return fix;
|
||
|
||
}
|
||
|
||
void driver::Scope::TriggerManager::stop() {
|
||
|
||
enable = false;
|
||
|
||
}
|
||
|
||
bool driver::Scope::TriggerManager::is_fixed() const {
|
||
|
||
return fixed;
|
||
|
||
}
|
||
|
||
void driver::Scope::TriggerManager::start() {
|
||
|
||
counter = 0;
|
||
fixed = false;
|
||
enable = true;
|
||
|
||
}
|
||
|
||
driver::Scope::TriggerManager::TriggerManager() :
|
||
condition( default_condition() ), enable(false), repeat_mode(false),
|
||
counter(0), threshold(0), prev_condition(true), fixed(false) {}
|
||
|
||
void driver::Scope::CaptureManager::setup( FrameIndex before_fix_frames,
|
||
FrameIndex after_fix_frames,
|
||
FrameIndex step ) {
|
||
|
||
before_trigger = true;
|
||
step_counter = 0;
|
||
|
||
before_trigger_frame_threshold = before_fix_frames;
|
||
after_trigger_frame_threshold = after_fix_frames;
|
||
step_threshold = step;
|
||
|
||
}
|
||
|
||
void driver::Scope::CaptureManager::fix( std::pair<Index, std::size_t> info ) {
|
||
|
||
before_trigger = false;
|
||
//step_counter = step_threshold;
|
||
|
||
head_index = info.first;
|
||
trigger_position = before_trigger_frame_counter = info.second;
|
||
|
||
}
|
||
|
||
bool driver::Scope::CaptureManager::at_shot() {
|
||
|
||
bool shot = false;
|
||
|
||
if( active ) {
|
||
|
||
step_counter = std::min( step_counter + 1, step_threshold );
|
||
|
||
if( step_counter == step_threshold ) {
|
||
|
||
step_counter = 0;
|
||
|
||
if( before_trigger ) {
|
||
|
||
before_trigger_frame_counter = std::min( before_trigger_frame_counter + 1, before_trigger_frame_threshold );
|
||
|
||
} else {
|
||
|
||
after_trigger_frame_counter = std::min( after_trigger_frame_counter + 1, after_trigger_frame_threshold );
|
||
|
||
if( after_trigger_frame_counter == after_trigger_frame_threshold ) {
|
||
|
||
active = false;
|
||
|
||
}
|
||
}
|
||
|
||
shot = true;
|
||
|
||
}
|
||
}
|
||
|
||
return shot;
|
||
|
||
}
|
||
|
||
void driver::Scope::CaptureManager::start() {
|
||
|
||
before_trigger_frame_counter = 0;
|
||
after_trigger_frame_counter = 0;
|
||
step_counter = step_threshold;
|
||
active = true;
|
||
|
||
}
|
||
|
||
bool driver::Scope::CaptureManager::is_active() const {
|
||
|
||
return active;
|
||
|
||
}
|
||
|
||
bool driver::Scope::CaptureManager::is_done() const {
|
||
|
||
return after_trigger_frame_counter == after_trigger_frame_threshold;
|
||
|
||
}
|
||
|
||
|
||
driver::Scope::Index driver::Scope::CaptureManager::head() const {
|
||
|
||
return head_index;
|
||
|
||
}
|
||
|
||
driver::Scope::CaptureManager::CaptureManager() : active(false),
|
||
before_trigger_frame_counter(0), after_trigger_frame_counter(0),
|
||
before_trigger_frame_threshold(0), after_trigger_frame_threshold(0),
|
||
trigger_position(0),
|
||
step_counter(0), step_threshold(0),
|
||
before_trigger(0), head_index() {}
|
||
|
||
|
||
struct DefaultCondition : public driver::Scope::Condition {
|
||
operator bool() const { return false; }
|
||
};
|
||
|
||
driver::Scope::Condition * driver::Scope::TriggerManager::default_condition() {
|
||
|
||
static DefaultCondition condition;
|
||
return &condition;
|
||
|
||
}
|
||
|
||
void driver::Scope::CaptureManager::stop() {
|
||
|
||
active = false;
|
||
|
||
}
|