plugins: A simple signal generator
Listens on a configurable SUT's global variable. On read access a signal pattern value is calculated and sent back to the SUT. Currently, only a superimposable sine wave signal form is implemented. Further signal forms can be implemented by inheriting from the abstract SignalForm class. Change-Id: I2e6cf49cd44797999691c9e9cf0c54dd3c96875e
This commit is contained in:
10
src/plugins/signalgenerator/CMakeLists.txt
Normal file
10
src/plugins/signalgenerator/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
set(PLUGIN_NAME signalgenerator)
|
||||||
|
|
||||||
|
set(MY_PLUGIN_SRCS
|
||||||
|
SignalGenerator.cc
|
||||||
|
SignalGenerator.hpp
|
||||||
|
)
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
## Build library
|
||||||
|
add_library(fail-${PLUGIN_NAME} ${MY_PLUGIN_SRCS})
|
||||||
63
src/plugins/signalgenerator/SignalGenerator.cc
Normal file
63
src/plugins/signalgenerator/SignalGenerator.cc
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include "SignalGenerator.hpp"
|
||||||
|
#include "sal/Listener.hpp"
|
||||||
|
#include "sal/Memory.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace fail;
|
||||||
|
|
||||||
|
bool SignalGenerator::run()
|
||||||
|
{
|
||||||
|
m_log << "Signalgenerator started. @ " << m_symbol << std::endl;
|
||||||
|
|
||||||
|
MemoryManager& mm = simulator.getMemoryManager();
|
||||||
|
MemReadListener l_mem(m_symbol.getAddress());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for EZS we currently use 8bit ADCs.
|
||||||
|
* @todo Make more versatile for future use.
|
||||||
|
*/
|
||||||
|
uint8_t value;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
simulator.addListenerAndResume(&l_mem);
|
||||||
|
value = handleEvent();
|
||||||
|
mm.setBytes(m_symbol.getAddress(), sizeof(value), &value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SignalGenerator::handleEvent(void)
|
||||||
|
{
|
||||||
|
double val = m_signal->calculate();
|
||||||
|
// Scale to uint8: 0 .. 255
|
||||||
|
val = val * 127; // -1: -127 .. +1: +127
|
||||||
|
val = val + 127; // -127: 0 .. +127 : 254
|
||||||
|
return (uint8_t) val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Sine::Sine(const SineParams_t param) {
|
||||||
|
m_params.push_back(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Sine::calculate() const {
|
||||||
|
simtime_t tps = ticksPerSecond();
|
||||||
|
if(tps == 0){
|
||||||
|
// Simulator speed not valid.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get simulation time in seconds.
|
||||||
|
double sec = (double)simulator.getTimerTicks() / tps;
|
||||||
|
|
||||||
|
// Sum up all sine waves
|
||||||
|
double val = 0;
|
||||||
|
for(Sine::SineParamsList_t::const_iterator it = m_params.begin();
|
||||||
|
it != m_params.end(); it++)
|
||||||
|
{
|
||||||
|
val += it->amplitude * sinus(it->freq_in_hz, sec);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
116
src/plugins/signalgenerator/SignalGenerator.hpp
Normal file
116
src/plugins/signalgenerator/SignalGenerator.hpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#ifndef __SIGNALGENERATOR_HPP__
|
||||||
|
#define __SIGNALGENERATOR_HPP__
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "efw/ExperimentFlow.hpp"
|
||||||
|
#include "config/FailConfig.hpp"
|
||||||
|
#include "util/Logger.hpp"
|
||||||
|
#include "util/ElfReader.hpp"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
static const float MYPI = 3.14159265358979323846f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief A simple signal generator
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class SignalForm
|
||||||
|
* @brief Abstract signal form to be generated by a SignalGenerator
|
||||||
|
* @see SignalGenerator
|
||||||
|
*/
|
||||||
|
class SignalForm {
|
||||||
|
|
||||||
|
mutable fail::Logger m_log;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Signalgenerator just calls the calculate method of a derived signal
|
||||||
|
* form.
|
||||||
|
*/
|
||||||
|
virtual double calculate(void) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SignalForm() : m_log("SigForm", false) {};
|
||||||
|
|
||||||
|
fail::simtime_t ticksPerSecond(void) const {
|
||||||
|
fail::simtime_t ticksPerSec = fail::simulator.getTimerTicksPerSecond();
|
||||||
|
if(ticksPerSec == 0){
|
||||||
|
m_log << "Warning: Timer ticks per second equals 0" << std::endl;
|
||||||
|
}
|
||||||
|
return ticksPerSec;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class SignalGenerator
|
||||||
|
* @brief Plugin to provide signal patterns on a specific memory location
|
||||||
|
*
|
||||||
|
* This plugin is intended for use in the realtime systems lecture.
|
||||||
|
* Based on the simulator tick, multiple sinus signal are generated.
|
||||||
|
*/
|
||||||
|
class SignalGenerator : public fail::ExperimentFlow
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const fail::ElfSymbol m_symbol; //!< the target's memory symbol the plugin is listening on to generate value
|
||||||
|
fail::Logger m_log; //!< debug output
|
||||||
|
const SignalForm *const m_signal; //!< Abstract signal form provided by the user
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param symbol The resulting signal value is placed in the SUT symbol
|
||||||
|
* @param signal The Signal form to be generated @see SignalForm
|
||||||
|
*/
|
||||||
|
SignalGenerator( const fail::ElfSymbol & symbol, SignalForm *signal ) : m_symbol(symbol), m_log("SigGen", false), m_signal(signal){}
|
||||||
|
|
||||||
|
bool run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Handle the memory event
|
||||||
|
*/
|
||||||
|
uint8_t handleEvent(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Sine
|
||||||
|
* @brief A sine wave signal
|
||||||
|
*
|
||||||
|
* Generating superimposed sine waves,
|
||||||
|
* according to the SineParams_t parameters.
|
||||||
|
*/
|
||||||
|
class Sine : public SignalForm {
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Parameter set for a single wave
|
||||||
|
struct SineParams_t {
|
||||||
|
double freq_in_hz; //!< Freqency in Hz
|
||||||
|
double amplitude; //!< between 0..1
|
||||||
|
SineParams_t(double f, double a) : freq_in_hz(f), amplitude(a) {};
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Multiple sine waves can be superimposed (e.g., summed up)
|
||||||
|
typedef std::vector<SineParams_t> SineParamsList_t;
|
||||||
|
SineParamsList_t m_params;
|
||||||
|
|
||||||
|
Sine(const SineParams_t param);
|
||||||
|
Sine(const SineParamsList_t paramlist) : m_params(paramlist) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate sinus value of frequency freq_hertz based on the given
|
||||||
|
* simulator time t (in seconds):
|
||||||
|
* \f$x = sin(2 pi f t)\f$
|
||||||
|
**/
|
||||||
|
double sinus(double freq_hertz, double t) const {
|
||||||
|
return sin((2. * MYPI * freq_hertz) * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
double calculate(void) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __SIGNALGENERATOR_HPP__
|
||||||
Reference in New Issue
Block a user