350 lines
7.4 KiB
C++
350 lines
7.4 KiB
C++
|
|
/*
|
|||
|
|
* Scope.cpp
|
|||
|
|
*
|
|||
|
|
* Created on: 27 <EFBFBD><EFBFBD><EFBFBD>. 2020 <EFBFBD>.
|
|||
|
|
* 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;
|
|||
|
|
|
|||
|
|
}
|