diff --git a/src/plugins/signalgenerator/CMakeLists.txt b/src/plugins/signalgenerator/CMakeLists.txt new file mode 100644 index 00000000..e2848e0c --- /dev/null +++ b/src/plugins/signalgenerator/CMakeLists.txt @@ -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}) diff --git a/src/plugins/signalgenerator/SignalGenerator.cc b/src/plugins/signalgenerator/SignalGenerator.cc new file mode 100644 index 00000000..6dd65816 --- /dev/null +++ b/src/plugins/signalgenerator/SignalGenerator.cc @@ -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; +} + diff --git a/src/plugins/signalgenerator/SignalGenerator.hpp b/src/plugins/signalgenerator/SignalGenerator.hpp new file mode 100644 index 00000000..dc59af53 --- /dev/null +++ b/src/plugins/signalgenerator/SignalGenerator.hpp @@ -0,0 +1,116 @@ +#ifndef __SIGNALGENERATOR_HPP__ + #define __SIGNALGENERATOR_HPP__ + +#include +#include "efw/ExperimentFlow.hpp" +#include "config/FailConfig.hpp" +#include "util/Logger.hpp" +#include "util/ElfReader.hpp" +#include + +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 + +/** + * @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 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__