Initial commit
This commit is contained in:
101
src/app/factory.cpp
Normal file
101
src/app/factory.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include "mcu/mcu.h"
|
||||
#include "xf/xf.h"
|
||||
#include "factory.h"
|
||||
#include "board/interface/buttonscontrollercallbackprovider.h"
|
||||
|
||||
extern "C" TIM_HandleTypeDef htim1; // Defined in main.c
|
||||
extern "C" ADC_HandleTypeDef hadc3; // Defined in main.c
|
||||
|
||||
oscilloscope::Controller Factory::_oscilloscopeController;
|
||||
oscilloscope::Gui Factory::_gui;
|
||||
external::FrequencyGenerator Factory::_fgen;
|
||||
oscilloscope::FreqGenController Factory::_fgenctrl;
|
||||
ButtonsController Factory::_bc;
|
||||
|
||||
void Factory_initialize()
|
||||
{
|
||||
Factory::initialize();
|
||||
|
||||
}
|
||||
|
||||
void Factory_build()
|
||||
{
|
||||
Factory::build();
|
||||
}
|
||||
|
||||
Factory::Factory()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// static
|
||||
void Factory::initialize()
|
||||
{
|
||||
Trace::out("---------------------------------------------");
|
||||
Trace::out("Initializing...");
|
||||
|
||||
// TODO: Uncomment code line below in order to call OscilloscopeController's initialize() method
|
||||
// getOscilloscopeController().initialize(getGui(), adcValuesBuffer, ADC_VALUES_BUFFER_SIZE);
|
||||
getFrequencyGenerator().initialize();
|
||||
getFreqGenController().initialize(getGui());
|
||||
#if (TOUCHGFX_BAREMETAL != 0)
|
||||
getTouchGfxTask().initialize();
|
||||
#endif // TOUCHGFX_BAREMETAL
|
||||
}
|
||||
|
||||
// static
|
||||
void Factory::build()
|
||||
{
|
||||
Trace::out("Building...");
|
||||
|
||||
HAL_ADC_Start_IT(&hadc3); // Start ADC conversion
|
||||
HAL_TIM_OC_Start_IT(&htim1, TIM_CHANNEL_1); // Start TIM1 with trigger channel 1
|
||||
|
||||
getOscilloscopeController().start();
|
||||
getGui().start();
|
||||
getButtonsController().registerCallback(&getFreqGenController(),
|
||||
(interface::ButtonsControllerCallbackProvider::CallbackMethod)&oscilloscope::FreqGenController::onButtonChanged);
|
||||
|
||||
getFreqGenController().start();
|
||||
getButtonsController().start();
|
||||
#if (TOUCHGFX_BAREMETAL != 0)
|
||||
getTouchGfxTask().start();
|
||||
#endif // TOUCHGFX_BAREMETAL
|
||||
|
||||
Trace::out("Running...");
|
||||
}
|
||||
|
||||
oscilloscope::Controller & Factory::getOscilloscopeController()
|
||||
{
|
||||
return oscilloscope::Controller::getInstance();
|
||||
}
|
||||
|
||||
//static
|
||||
oscilloscope::Gui & Factory::getGui()
|
||||
{
|
||||
return _gui;
|
||||
}
|
||||
|
||||
//static
|
||||
ButtonsController& Factory::getButtonsController() {
|
||||
return _bc;
|
||||
}
|
||||
|
||||
//static
|
||||
oscilloscope::FreqGenController& Factory::getFreqGenController() {
|
||||
return _fgenctrl;
|
||||
}
|
||||
|
||||
|
||||
#if (TOUCHGFX_BAREMETAL != 0)
|
||||
// static
|
||||
TouchGfxTask & Factory::getTouchGfxTask()
|
||||
{
|
||||
static TouchGfxTask touchGfxTask;
|
||||
return touchGfxTask;
|
||||
}
|
||||
#endif // TOUCHGFX_BAREMETAL
|
||||
|
||||
FrequencyGenerator& Factory::getFrequencyGenerator() {
|
||||
return _fgen;
|
||||
}
|
66
src/app/factory.h
Normal file
66
src/app/factory.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef APP_FACTORY_H
|
||||
#define APP_FACTORY_H
|
||||
|
||||
//
|
||||
// What is seen only by the C++ compiler
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "main.h"
|
||||
#include "oscilloscopecontroller.h"
|
||||
#include "gui.h"
|
||||
#include "config/touchgfx-config.h"
|
||||
#if (TOUCHGFX_BAREMETAL != 0)
|
||||
#include "touchgfxtask.h"
|
||||
#endif // TOUCHGFX_BAREMETAL
|
||||
#include "mdw/ext-freqgen/frequencygenerator.h"
|
||||
#include "app/freqgencontroller.h"
|
||||
#include "board/buttonscontroller.h"
|
||||
using external::FrequencyGenerator;
|
||||
|
||||
/**
|
||||
* @brief Factory creating all objects/components and relations between them.
|
||||
*/
|
||||
class Factory
|
||||
{
|
||||
public:
|
||||
Factory(); ///< Constructor
|
||||
|
||||
static void initialize(); ///< Initializes the factory
|
||||
static void build(); ///< Creates components and initializes relations
|
||||
|
||||
#if (TOUCHGFX_BAREMETAL != 0)
|
||||
static TouchGfxTask & getTouchGfxTask();
|
||||
#endif // TOUCHGFX_BAREMETAL
|
||||
|
||||
|
||||
static oscilloscope::Controller & getOscilloscopeController();
|
||||
static oscilloscope::Gui & getGui();
|
||||
static ButtonsController& getButtonsController();
|
||||
static FrequencyGenerator& getFrequencyGenerator();
|
||||
static oscilloscope::FreqGenController& getFreqGenController();
|
||||
|
||||
protected:
|
||||
static oscilloscope::Controller _oscilloscopeController;
|
||||
static oscilloscope::Gui _gui;
|
||||
static external::FrequencyGenerator _fgen;
|
||||
static oscilloscope::FreqGenController _fgenctrl;
|
||||
static ButtonsController _bc;
|
||||
};
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
//
|
||||
// What is seen by the C and C++ compiler
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
void Factory_initialize();
|
||||
void Factory_build();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // APP_FACTORY_H
|
305
src/app/freqgencontroller.cpp
Normal file
305
src/app/freqgencontroller.cpp
Normal file
@ -0,0 +1,305 @@
|
||||
#include "freqgencontroller.h"
|
||||
#include "factory.h"
|
||||
#include "trace/trace.h"
|
||||
#include <assert.h>
|
||||
#include "event/evButtonPressed.h"
|
||||
#include "event/events.h"
|
||||
|
||||
namespace oscilloscope
|
||||
{
|
||||
|
||||
FreqGenController* FreqGenController::_instance = nullptr;
|
||||
|
||||
FreqGenController::FreqGenController():
|
||||
_pGui(nullptr)
|
||||
{
|
||||
assert (_instance==nullptr);
|
||||
_instance = this;
|
||||
if (EXTFREQGEN_START_FREQUENCY == HZ_50 ||
|
||||
EXTFREQGEN_START_FREQUENCY == HZ_110 ||
|
||||
EXTFREQGEN_START_FREQUENCY == HZ_240 ||
|
||||
EXTFREQGEN_START_FREQUENCY == HZ_370 ||
|
||||
EXTFREQGEN_START_FREQUENCY == HZ_500 ||
|
||||
EXTFREQGEN_START_FREQUENCY == HZ_700 ||
|
||||
EXTFREQGEN_START_FREQUENCY == HZ_1000 ||
|
||||
EXTFREQGEN_START_FREQUENCY == HZ_5000 ||
|
||||
EXTFREQGEN_START_FREQUENCY == HZ_10000)
|
||||
{
|
||||
_frequency = EXTFREQGEN_START_FREQUENCY;
|
||||
}
|
||||
else
|
||||
{
|
||||
_frequency = HZ_1000;
|
||||
}
|
||||
if (EXTFREQGEN_START_WAVEFORM == SINUS ||
|
||||
EXTFREQGEN_START_WAVEFORM == TRIANGLE ||
|
||||
EXTFREQGEN_START_WAVEFORM == SQUARE)
|
||||
{
|
||||
_mode = EXTFREQGEN_START_WAVEFORM;
|
||||
}
|
||||
else
|
||||
{
|
||||
_mode = SINUS;
|
||||
}
|
||||
change();
|
||||
|
||||
state = ST_INIT;
|
||||
}
|
||||
|
||||
void FreqGenController::onButtonChanged(uint16_t buttonIndex, bool pressed) {
|
||||
if (pressed)
|
||||
{
|
||||
GEN(evButtonPressed(buttonIndex));
|
||||
}
|
||||
}
|
||||
|
||||
FreqGenController* FreqGenController::getInstance() {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
|
||||
XFEventStatus FreqGenController::processEvent() {
|
||||
XFEventStatus retVal = XFEventStatus::NotConsumed;
|
||||
FCG_STATES oldState = state;
|
||||
const XFEvent* ev = getCurrentEvent();
|
||||
switch (state)
|
||||
{
|
||||
case ST_INIT:
|
||||
if (ev->getEventType()==XFEvent::Initial)
|
||||
{
|
||||
state = ST_WAITBUTTON;
|
||||
}
|
||||
break;
|
||||
case ST_WAITBUTTON:
|
||||
if (ev->getEventType()==XFEvent::Event && ev->getId() == evButtonPressedId)
|
||||
{
|
||||
switch (((evButtonPressed*) ev)->buttonIndex())
|
||||
{
|
||||
case 1:
|
||||
state = ST_CHANGEFREQDOWN;
|
||||
break;
|
||||
case 2:
|
||||
state = ST_CHANGEFREQUP;
|
||||
break;
|
||||
case 3:
|
||||
state = ST_CHANGEMODE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ST_CHANGEFREQUP:
|
||||
case ST_CHANGEFREQDOWN:
|
||||
case ST_CHANGEMODE:
|
||||
if (ev->getEventType()==XFEvent::NullTransition )
|
||||
{
|
||||
state = ST_WAITBUTTON;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (oldState != state)
|
||||
{
|
||||
retVal = XFEventStatus::Consumed;
|
||||
switch (state)
|
||||
{
|
||||
case ST_INIT:
|
||||
break;
|
||||
case ST_WAITBUTTON:
|
||||
break;
|
||||
case ST_CHANGEFREQUP:
|
||||
frequencyUp();
|
||||
change();
|
||||
GEN(XFNullTransition());
|
||||
break;
|
||||
case ST_CHANGEFREQDOWN:
|
||||
frequencyDown();
|
||||
change();
|
||||
GEN(XFNullTransition());
|
||||
break;
|
||||
case ST_CHANGEMODE:
|
||||
shiftMode();
|
||||
change();
|
||||
GEN(XFNullTransition());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void FreqGenController::start() {
|
||||
startBehavior();
|
||||
}
|
||||
|
||||
void FreqGenController::frequencyUp() {
|
||||
//change the frequency up
|
||||
switch (_frequency)
|
||||
{
|
||||
case HZ_50:
|
||||
_frequency = HZ_110;
|
||||
break;
|
||||
case HZ_110:
|
||||
_frequency = HZ_240;
|
||||
break;
|
||||
case HZ_240:
|
||||
_frequency = HZ_370;
|
||||
break;
|
||||
case HZ_370:
|
||||
_frequency = HZ_500;
|
||||
break;
|
||||
case HZ_500:
|
||||
_frequency = HZ_700;
|
||||
break;
|
||||
case HZ_700:
|
||||
_frequency = HZ_1000;
|
||||
break;
|
||||
case HZ_1000:
|
||||
_frequency = HZ_5000;
|
||||
break;
|
||||
case HZ_5000:
|
||||
_frequency = HZ_10000;
|
||||
break;
|
||||
case HZ_10000:
|
||||
_frequency = HZ_50;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Trace::out("Frequency up to %s", toString(_frequency).c_str());
|
||||
|
||||
// Update LCD display
|
||||
gui().setFreqGenFrequencyText(toString(_frequency));
|
||||
}
|
||||
|
||||
void FreqGenController::frequencyDown() {
|
||||
//change the frequency down
|
||||
switch (_frequency)
|
||||
{
|
||||
case HZ_50:
|
||||
_frequency = HZ_10000;
|
||||
break;
|
||||
case HZ_110:
|
||||
_frequency = HZ_50;
|
||||
break;
|
||||
case HZ_240:
|
||||
_frequency = HZ_110;
|
||||
break;
|
||||
case HZ_370:
|
||||
_frequency = HZ_240;
|
||||
break;
|
||||
case HZ_500:
|
||||
_frequency = HZ_370;
|
||||
break;
|
||||
case HZ_700:
|
||||
_frequency = HZ_500;
|
||||
break;
|
||||
case HZ_1000:
|
||||
_frequency = HZ_700;
|
||||
break;
|
||||
case HZ_5000:
|
||||
_frequency = HZ_1000;
|
||||
break;
|
||||
case HZ_10000:
|
||||
_frequency = HZ_5000;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Trace::out("Frequency down to %s", toString(_frequency).c_str());
|
||||
|
||||
// Update LCD display
|
||||
gui().setFreqGenFrequencyText(toString(_frequency));
|
||||
}
|
||||
|
||||
void FreqGenController::shiftMode() {
|
||||
//change the waveform
|
||||
switch (_mode)
|
||||
{
|
||||
case SINUS:
|
||||
_mode = TRIANGLE;
|
||||
if (EXTFREQGEN_NOTIFICATION_TRACE == 1)
|
||||
{
|
||||
Trace::out("Triangle\n");
|
||||
gui().setFreqGenWaveformText("Tria -");
|
||||
}
|
||||
break;
|
||||
case TRIANGLE :
|
||||
_mode = SQUARE;
|
||||
if (EXTFREQGEN_NOTIFICATION_TRACE == 1)
|
||||
{
|
||||
Trace::out("Square\n");
|
||||
gui().setFreqGenWaveformText("Rect -");
|
||||
}
|
||||
break;
|
||||
case SQUARE :
|
||||
_mode = SINUS;
|
||||
if (EXTFREQGEN_NOTIFICATION_TRACE == 1)
|
||||
{
|
||||
Trace::out("Sine\n");
|
||||
gui().setFreqGenWaveformText("Sine -");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FreqGenController::initialize(oscilloscope::Gui & gui) {
|
||||
_pGui = &gui;
|
||||
Factory::getFrequencyGenerator().setFrequency(_frequency);
|
||||
Factory::getFrequencyGenerator().setWaveForm(_mode);
|
||||
}
|
||||
|
||||
void FreqGenController::change() {
|
||||
Factory::getFrequencyGenerator().setWaveForm(_mode);
|
||||
Factory::getFrequencyGenerator().setFrequency(_frequency);
|
||||
}
|
||||
|
||||
//static
|
||||
std::string FreqGenController::toString(const Frequency & frequency)
|
||||
{
|
||||
std::string freqString("n/a");
|
||||
|
||||
switch (frequency)
|
||||
{
|
||||
case HZ_50:
|
||||
freqString = "50 Hz";
|
||||
break;
|
||||
case HZ_110:
|
||||
freqString = "110 Hz";
|
||||
break;
|
||||
case HZ_240:
|
||||
freqString = "240 Hz";
|
||||
break;
|
||||
case HZ_370:
|
||||
freqString = "370 Hz";
|
||||
break;
|
||||
case HZ_500:
|
||||
freqString = "500 Hz";
|
||||
break;
|
||||
case HZ_700:
|
||||
freqString = "700 Hz";
|
||||
break;
|
||||
case HZ_1000:
|
||||
freqString = "1 kHz";
|
||||
break;
|
||||
case HZ_5000:
|
||||
freqString = "5 kHz";
|
||||
break;
|
||||
case HZ_10000:
|
||||
freqString = "10 kHz";
|
||||
break;
|
||||
}
|
||||
|
||||
return freqString;
|
||||
}
|
||||
|
||||
} /* namespace oscilloscope */
|
||||
|
||||
|
81
src/app/freqgencontroller.h
Normal file
81
src/app/freqgencontroller.h
Normal file
@ -0,0 +1,81 @@
|
||||
#ifndef APP_FREQGENCONTROLLER_H
|
||||
#define APP_FREQGENCONTROLLER_H
|
||||
|
||||
#include <cassert>
|
||||
#include <stdint.h>
|
||||
#include "config/ext-freqgen-config.h"
|
||||
#include "xf/behavior.h"
|
||||
#include "board/interface/buttonscontrollercallbackprovider.h"
|
||||
#include "ext-26pin/ext_26pin.h"
|
||||
|
||||
namespace oscilloscope
|
||||
{
|
||||
|
||||
class Gui;
|
||||
|
||||
typedef enum _Frequency
|
||||
{
|
||||
HZ_50 = 50,
|
||||
HZ_110 =110,
|
||||
HZ_240 = 240,
|
||||
HZ_370 = 370,
|
||||
HZ_500 = 500,
|
||||
HZ_700 = 700,
|
||||
HZ_1000 = 1000,
|
||||
HZ_5000 = 5000,
|
||||
HZ_10000 = 10000
|
||||
} Frequency;
|
||||
|
||||
/**
|
||||
* @brief Frequency generator controller to drive external MinGen module with buttons.
|
||||
*/
|
||||
class FreqGenController : public interface::ButtonsControllerCallbackProvider,
|
||||
public XFBehavior
|
||||
{
|
||||
//internal types
|
||||
public:
|
||||
typedef enum _FGC_STATES
|
||||
{
|
||||
ST_INIT,
|
||||
ST_WAITBUTTON,
|
||||
ST_CHANGEFREQUP,
|
||||
ST_CHANGEFREQDOWN,
|
||||
ST_CHANGEMODE
|
||||
} FCG_STATES;
|
||||
|
||||
public:
|
||||
FreqGenController();
|
||||
static FreqGenController* getInstance();
|
||||
|
||||
//interface ButtonsControllerCallbackProvider
|
||||
public:
|
||||
void onButtonChanged(uint16_t buttonIndex, bool pressed);
|
||||
|
||||
//interface XFBehavior
|
||||
public:
|
||||
XFEventStatus processEvent();
|
||||
void start();
|
||||
void initialize(oscilloscope::Gui & gui);
|
||||
|
||||
protected:
|
||||
inline oscilloscope::Gui & gui() const { assert(_pGui); return *_pGui; }
|
||||
|
||||
// internal methods
|
||||
private:
|
||||
void frequencyUp();
|
||||
void frequencyDown();
|
||||
void shiftMode();
|
||||
void change();
|
||||
|
||||
static std::string toString(const Frequency & frequency);
|
||||
|
||||
private:
|
||||
static FreqGenController* _instance;
|
||||
oscilloscope::Gui * _pGui;
|
||||
Frequency _frequency;
|
||||
f_mode _mode;
|
||||
FCG_STATES state;
|
||||
};
|
||||
|
||||
} /* namespace oscilloscope */
|
||||
#endif // APP_FREQGENCONTROLLER_H
|
105
src/app/gui.cpp
Normal file
105
src/app/gui.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include "trace/trace.h"
|
||||
#include "gui.h"
|
||||
#include "TouchGFX/gui/include/gui/mainview_screen/MainViewView.hpp"
|
||||
#include "TouchGFX/gui/include/gui/model/Model.hpp"
|
||||
|
||||
#define TOUCH_THREAD_STACK_SIZE 2048
|
||||
|
||||
namespace oscilloscope {
|
||||
|
||||
Gui* Gui::_instance = nullptr;
|
||||
|
||||
Gui::Gui() :
|
||||
_pGuiObserver(nullptr),
|
||||
_redLedOn(false),
|
||||
_xAxisPixelsPerField(roundf(460.0/8)) // Width of the chart graph divided by the number of divisions to show
|
||||
{
|
||||
if(_instance==nullptr){
|
||||
_instance = this;
|
||||
}
|
||||
}
|
||||
|
||||
Gui* Gui::getInstance() {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
bool Gui::registerObserver(interface::GuiObserver * pGuiObserver)
|
||||
{
|
||||
if (!_pGuiObserver and pGuiObserver)
|
||||
{
|
||||
_pGuiObserver = pGuiObserver;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Gui::start()
|
||||
{
|
||||
}
|
||||
|
||||
void Gui::drawGraphPoints(uint16_t * values, uint16_t maxSize, float xScale /* = 1 */)
|
||||
{
|
||||
Model* model = Model::getInstance();
|
||||
if(model!=nullptr){
|
||||
model->setGraphPoints(values, maxSize, xScale);
|
||||
}
|
||||
}
|
||||
|
||||
bool Gui::isRedLedEnabled() const
|
||||
{
|
||||
return _redLedOn;
|
||||
}
|
||||
|
||||
void Gui::setRedLed(bool enable)
|
||||
{
|
||||
_redLedOn = enable;
|
||||
}
|
||||
|
||||
bool Gui::isOscilloscopePageEnabled() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Gui::setTimeDivisionText(std::string text)
|
||||
{
|
||||
Model* model = Model::getInstance();
|
||||
if(model!=nullptr){
|
||||
model->setDivTimLabel(text);
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::setFreqGenWaveformText(std::string text)
|
||||
{
|
||||
Model* model = Model::getInstance();
|
||||
if(model!=nullptr){
|
||||
model->setModeSignal(text);
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::setFreqGenFrequencyText(std::string text)
|
||||
{
|
||||
Model* model = Model::getInstance();
|
||||
if(model!=nullptr){
|
||||
model->setFreqSignal(text);
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::onButtonTimePlusPressed()
|
||||
{
|
||||
_pGuiObserver->onButtonTimePlusPressed();
|
||||
}
|
||||
|
||||
void Gui::onButtonTimeMinusPressed()
|
||||
{
|
||||
_pGuiObserver->onButtonTimeMinusPressed();
|
||||
}
|
||||
|
||||
void Gui::onCheckBoxTriggerCheckState(bool checked)
|
||||
{
|
||||
_pGuiObserver->onCheckBoxTriggerCheckState(checked);
|
||||
}
|
||||
|
||||
} // namespace oscilloscope
|
55
src/app/gui.h
Normal file
55
src/app/gui.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef APP_GUI_H
|
||||
#define APP_GUI_H
|
||||
|
||||
#include "interface/guiobserver.h"
|
||||
|
||||
namespace oscilloscope {
|
||||
|
||||
/**
|
||||
* @brief The GUI (Graphical User Interface) class is handling the oscilloscope view on the LCD.
|
||||
*
|
||||
* The GUI class uses a graphical library to show the oscilloscope view.
|
||||
*
|
||||
* Internally, all requests are forwarded to the TouchGFX generated classes.
|
||||
*
|
||||
* Note: Keep in mind that the internal graph element provides only a maximum of 460 data points!
|
||||
*/
|
||||
class Gui
|
||||
{
|
||||
public:
|
||||
Gui();
|
||||
|
||||
static Gui* getInstance();
|
||||
|
||||
bool registerObserver(interface::GuiObserver * pGuiObserver);
|
||||
void start();
|
||||
|
||||
void drawGraphPoints(uint16_t * values, uint16_t maxSize, float xScale = 1);
|
||||
|
||||
bool isRedLedEnabled() const;
|
||||
void setRedLed(bool enable);
|
||||
|
||||
bool isOscilloscopePageEnabled() const;
|
||||
|
||||
void setTimeDivisionText(std::string text);
|
||||
void setFreqGenWaveformText(std::string text);
|
||||
void setFreqGenFrequencyText(std::string text);
|
||||
|
||||
inline float getXAxisPixelsPerField() const { return _xAxisPixelsPerField; }
|
||||
|
||||
void onButtonTimePlusPressed();
|
||||
void onButtonTimeMinusPressed();
|
||||
void onCheckBoxTriggerCheckState(bool checked);
|
||||
|
||||
protected:
|
||||
inline interface::GuiObserver & observer() const { assert(_pGuiObserver); return *_pGuiObserver; }
|
||||
|
||||
protected:
|
||||
static Gui* _instance;
|
||||
interface::GuiObserver * _pGuiObserver; ///< GUI observer notified about GUI events.
|
||||
bool _redLedOn;
|
||||
float _xAxisPixelsPerField; ///< Number of pixels per field on the x-axis.
|
||||
};
|
||||
|
||||
} // namespace oscilloscope
|
||||
#endif // APP_GUI_H
|
0
src/app/interface/guiobserver.cpp
Normal file
0
src/app/interface/guiobserver.cpp
Normal file
22
src/app/interface/guiobserver.h
Normal file
22
src/app/interface/guiobserver.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef INTERFACE_GUI_OBSERVER_H
|
||||
#define INTERFACE_GUI_OBSERVER_H
|
||||
|
||||
namespace interface {
|
||||
|
||||
class GuiObserver
|
||||
{
|
||||
public:
|
||||
virtual ~GuiObserver() {}
|
||||
|
||||
virtual void onButtonTimePlusPressed() = 0;
|
||||
virtual void onButtonTimeMinusPressed() = 0;
|
||||
virtual void onCheckBoxTriggerCheckState(bool checked) = 0;
|
||||
|
||||
virtual uint32_t getTDivCount() const = 0; // Returns the of x-axis grid count
|
||||
|
||||
protected:
|
||||
GuiObserver() {}
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // INTERFACE_GUI_OBSERVER_H
|
150
src/app/oscilloscopecontroller.cpp
Normal file
150
src/app/oscilloscopecontroller.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include <assert.h>
|
||||
#include "trace/trace.h"
|
||||
#include "xf/eventstatus.h"
|
||||
#include "event/evcheckboxtrigger.h"
|
||||
#include "main.h"
|
||||
#include "gui.h"
|
||||
#include "oscilloscopecontroller.h"
|
||||
|
||||
namespace oscilloscope {
|
||||
|
||||
Controller * Controller::_pInstance(nullptr);
|
||||
|
||||
const TDivOption Controller::_tdivOptions[] = {{TDIV_500us, "500 us / div"},
|
||||
{TDIV_1ms, "1 ms / div"},
|
||||
{TDIV_2ms, "2 ms / div"},
|
||||
{TDIV_5ms, "5 ms / div"},
|
||||
{TDIV_10ms, "10 ms / div"}};
|
||||
|
||||
Controller::Controller() :
|
||||
_pGui(nullptr),
|
||||
_adcValuesBuffer(nullptr),
|
||||
_adcValuesBufferSize(0),
|
||||
_tdivValue(TDIV_1ms)
|
||||
{
|
||||
assert(!_pInstance); // Only one instance of this class allowed!
|
||||
_pInstance = this;
|
||||
}
|
||||
|
||||
//static
|
||||
Controller & Controller::getInstance()
|
||||
{
|
||||
assert(_pInstance); // Create first an instance!
|
||||
return *_pInstance;
|
||||
}
|
||||
|
||||
void Controller::initialize(Gui & gui, uint16_t * adcValuesBuffer, uint32_t adcValuesBufferSize)
|
||||
{
|
||||
_pGui = &gui;
|
||||
_adcValuesBuffer = adcValuesBuffer;
|
||||
_adcValuesBufferSize = adcValuesBufferSize;
|
||||
|
||||
gui.registerObserver(this); // Get notified about GUI events
|
||||
}
|
||||
|
||||
void Controller::start()
|
||||
{
|
||||
startBehavior();
|
||||
}
|
||||
|
||||
XFEventStatus Controller::processEvent()
|
||||
{
|
||||
if (!_adcValuesBuffer)
|
||||
{
|
||||
Trace::out("oscilloscope::Controller Error: Attribute '_adcValuesBuffer' not set!");
|
||||
}
|
||||
|
||||
assert(_adcValuesBuffer);
|
||||
assert(_adcValuesBufferSize > 0);
|
||||
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::Initial)
|
||||
{
|
||||
scheduleTimeout(TIMEOUT_ID, TIMEOUT_INTERVAL);
|
||||
|
||||
doShowAnalogSignal();
|
||||
}
|
||||
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::Timeout &&
|
||||
getCurrentTimeout()->getId() == TIMEOUT_ID)
|
||||
{
|
||||
scheduleTimeout(TIMEOUT_ID, TIMEOUT_INTERVAL);
|
||||
|
||||
doShowAnalogSignal();
|
||||
}
|
||||
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::Event &&
|
||||
getCurrentEvent()->getId() == BTN_PLUS_ID)
|
||||
{
|
||||
doButtonTimePlusPressed();
|
||||
}
|
||||
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::Event &&
|
||||
getCurrentEvent()->getId() == BTN_MINUS_ID)
|
||||
{
|
||||
doButtonTimeMinusPressed();
|
||||
}
|
||||
|
||||
return XFEventStatus::Consumed;
|
||||
}
|
||||
|
||||
void Controller::onButtonTimePlusPressed()
|
||||
{
|
||||
XFEvent* evButtonPlus =new XFEvent(XFEvent::Event, BTN_PLUS_ID, this);
|
||||
|
||||
pushEvent(evButtonPlus);
|
||||
}
|
||||
|
||||
void Controller::onButtonTimeMinusPressed()
|
||||
{
|
||||
XFEvent* evButtonMinus =new XFEvent(XFEvent::Event, BTN_MINUS_ID, this);
|
||||
|
||||
pushEvent(evButtonMinus);
|
||||
}
|
||||
|
||||
void Controller::onCheckBoxTriggerCheckState(bool checked)
|
||||
{
|
||||
Trace::out("Trigger checkbox: %s", (checked) ? "checked" : "unchecked");
|
||||
|
||||
GEN(evCheckBoxTrigger(checked, CHECK_BOX_TRIGGER_ID));
|
||||
}
|
||||
|
||||
void Controller::doShowAnalogSignal()
|
||||
{
|
||||
// TODO: Call gui().drawGraphPoints() with the appropriate data.
|
||||
}
|
||||
|
||||
void Controller::doButtonTimePlusPressed()
|
||||
{
|
||||
if (_tdivValue < (TDIV_MAX - 1))
|
||||
{
|
||||
_tdivValue = (TDivValue)(_tdivValue + 1);
|
||||
|
||||
gui().setTimeDivisionText(getText(_tdivValue));
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::doButtonTimeMinusPressed()
|
||||
{
|
||||
if (_tdivValue > (TDIV_MIN + 1))
|
||||
{
|
||||
_tdivValue = (TDivValue)(_tdivValue - 1);
|
||||
|
||||
gui().setTimeDivisionText(getText(_tdivValue));
|
||||
}
|
||||
}
|
||||
|
||||
std::string Controller::getText(TDivValue tdivValue)
|
||||
{
|
||||
const uint32_t count = sizeof(_tdivOptions)/sizeof(_tdivOptions[0]);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
if (_tdivOptions[i].tdivValue == tdivValue)
|
||||
{
|
||||
return _tdivOptions[i].text;
|
||||
}
|
||||
}
|
||||
return "n/a";
|
||||
}
|
||||
|
||||
} // namespace oscilloscope
|
92
src/app/oscilloscopecontroller.h
Normal file
92
src/app/oscilloscopecontroller.h
Normal file
@ -0,0 +1,92 @@
|
||||
#ifndef OSCILLOSCOPECONTROLLER_H
|
||||
#define OSCILLOSCOPECONTROLLER_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include "xf/behavior.h"
|
||||
#include "interface/guiobserver.h"
|
||||
|
||||
namespace oscilloscope {
|
||||
class Gui;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TDIV_MIN = 0,
|
||||
TDIV_500us,
|
||||
TDIV_1ms,
|
||||
TDIV_2ms,
|
||||
TDIV_5ms,
|
||||
TDIV_10ms,
|
||||
TDIV_MAX
|
||||
} TDivValue;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TDivValue tdivValue;
|
||||
std::string text;
|
||||
} TDivOption;
|
||||
|
||||
/**
|
||||
* @brief The Oscilloscope Controller
|
||||
*
|
||||
* Responsible to provide and update oscilloscope data. All input
|
||||
* (touch screen, signal measurement data) comes to the controller
|
||||
* and updates then the view(s) accordingly.
|
||||
*/
|
||||
class Controller : public XFBehavior,
|
||||
public interface::GuiObserver
|
||||
{
|
||||
public:
|
||||
Controller();
|
||||
virtual ~Controller() {}
|
||||
|
||||
static Controller & getInstance();
|
||||
|
||||
void initialize(Gui & gui, uint16_t * adcValuesBuffer, uint32_t adcValuesBufferSize);
|
||||
|
||||
void start();
|
||||
|
||||
inline TDivValue getTDivValue() const { return _tdivValue; }
|
||||
|
||||
// XFReactive interface implementation
|
||||
protected:
|
||||
XFEventStatus processEvent() override;
|
||||
|
||||
// GuiObserver interface implementation
|
||||
protected:
|
||||
void onButtonTimePlusPressed() override;
|
||||
void onButtonTimeMinusPressed() override;
|
||||
void onCheckBoxTriggerCheckState(bool checked) override;
|
||||
uint32_t getTDivCount() const override { return 8; };
|
||||
|
||||
protected:
|
||||
void doShowAnalogSignal();
|
||||
void doButtonTimePlusPressed();
|
||||
void doButtonTimeMinusPressed();
|
||||
inline Gui & gui() const { assert(_pGui); return *_pGui; }
|
||||
|
||||
std::string getText(TDivValue tdivValue);
|
||||
|
||||
protected:
|
||||
static Controller * _pInstance;
|
||||
|
||||
Gui * _pGui;
|
||||
uint16_t * _adcValuesBuffer;
|
||||
uint32_t _adcValuesBufferSize;
|
||||
|
||||
const int TIMEOUT_ID = 0;
|
||||
const int TIMEOUT_INTERVAL = 20;
|
||||
|
||||
enum {
|
||||
BTN_PLUS_ID = 0,
|
||||
BTN_MINUS_ID = 1,
|
||||
CHECK_BOX_TRIGGER_ID = 2
|
||||
} EventId;
|
||||
|
||||
TDivValue _tdivValue;
|
||||
|
||||
static const TDivOption _tdivOptions[];
|
||||
};
|
||||
|
||||
} // namespace oscilloscope
|
||||
#endif // OSCILLOSCOPECONTROLLER_H
|
50
src/app/touchgfxtask.cpp
Normal file
50
src/app/touchgfxtask.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "config/touchgfx-config.h"
|
||||
|
||||
#if (TOUCHGFX_BAREMETAL != 0)
|
||||
|
||||
#include "app_touchgfx.h"
|
||||
#include "gui/common/FrontendHeap.hpp"
|
||||
#include "touchgfxtask.h"
|
||||
|
||||
extern "C" void touchgfx_init();
|
||||
extern "C" void touchgfx_taskEntry();
|
||||
|
||||
TouchGfxTask::TouchGfxTask():
|
||||
interval_(20)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TouchGfxTask::initialize()
|
||||
{
|
||||
touchgfx_init();
|
||||
|
||||
}
|
||||
|
||||
void TouchGfxTask::start()
|
||||
{
|
||||
startBehavior();
|
||||
}
|
||||
|
||||
XFEventStatus TouchGfxTask::processEvent()
|
||||
{
|
||||
// Generate a timeout on startup. Want to call touchgfx_taskEntry()
|
||||
// every x milliseconds
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::Initial)
|
||||
{
|
||||
scheduleTimeout(1, 20);
|
||||
}
|
||||
|
||||
// Call touchgfx_taskEntry on timeout
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::Timeout and
|
||||
getCurrentTimeout()->getId() == 1)
|
||||
{
|
||||
touchgfx_taskEntry();
|
||||
|
||||
scheduleTimeout(1, 20);
|
||||
}
|
||||
|
||||
return XFEventStatus::Consumed;
|
||||
}
|
||||
|
||||
#endif // TOUCHGFX_BAREMETAL
|
28
src/app/touchgfxtask.h
Normal file
28
src/app/touchgfxtask.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef TOUCHGFXTASK_H
|
||||
#define TOUCHGFXTASK_H
|
||||
|
||||
#include "config/touchgfx-config.h"
|
||||
|
||||
#if (TOUCHGFX_BAREMETAL != 0)
|
||||
#include "xf/behavior.h"
|
||||
|
||||
/**
|
||||
* @brief TouchGFX task used in IDF and/or bare-metal environments to drive LCD display.
|
||||
*/
|
||||
class TouchGfxTask : public XFBehavior
|
||||
{
|
||||
public:
|
||||
TouchGfxTask();
|
||||
|
||||
void initialize();
|
||||
void start();
|
||||
|
||||
protected:
|
||||
XFEventStatus processEvent() override;
|
||||
|
||||
protected:
|
||||
const int32_t interval_;
|
||||
};
|
||||
|
||||
#endif // TOUCHGFX_BAREMETAL
|
||||
#endif // TOUCHGFXTASK_H
|
8
src/config/buttonscontroller-config.h
Normal file
8
src/config/buttonscontroller-config.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef BOARD_BUTTONSCONTROLLER_CONFIG_H
|
||||
#define BOARD_BUTTONSCONTROLLER_CONFIG_H
|
||||
|
||||
#define BUTTONSCONTROLLER_EXCLUDE_FROM_BUILD 0 /**< Default: 0; ButtonsController is needed in this project. */
|
||||
#define BUTTONSCONTROLLER_DEBOUNCE_TIME 10 /**< Time in milliseconds to debounce buttons. */
|
||||
#define TRACE_BUTTONSCONTROLLER_NOTIFICATIONS 0 /**< Enables trace notification messages. */
|
||||
|
||||
#endif // BOARD_BUTTONSCONTROLLER_CONFIG_H
|
27
src/config/ext-freqgen-config.h
Normal file
27
src/config/ext-freqgen-config.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* ext-freqgen-config.h
|
||||
*
|
||||
* Created on: 24 Nov 2020
|
||||
* Author: rim
|
||||
*/
|
||||
|
||||
#ifndef EXT_FREQGEN_CONFIG_H_
|
||||
#define EXT_FREQGEN_CONFIG_H_
|
||||
|
||||
#define EXTFREQGEN_NOTIFICATION_TRACE 1 // (0,1) default=1 trace out of waveform and frequency
|
||||
#define EXTFREQGEN_START_FREQUENCY HZ_1000 // one of these:
|
||||
// HZ_50 = 50,
|
||||
// HZ_110 =110,
|
||||
// HZ_240 = 240,
|
||||
// HZ_370 = 370,
|
||||
// HZ_500 = 500,
|
||||
// HZ_700 = 700,
|
||||
// HZ_1000 = 1000,
|
||||
// HZ_5000 = 5000,
|
||||
// HZ_10000 = 10000
|
||||
#define EXTFREQGEN_START_WAVEFORM TRIANGLE // one of these:
|
||||
// SINUS
|
||||
// TRIANGLE
|
||||
// SQUARE
|
||||
|
||||
#endif /* EXT_FREQGEN_CONFIG_H_ */
|
10
src/config/touchgfx-config.h
Normal file
10
src/config/touchgfx-config.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef TOUCHGFX_CONFIG_H
|
||||
#define TOUCHGFX_CONFIG_H
|
||||
|
||||
/**
|
||||
* Waring: Only one PORT define should be enabled at a time!
|
||||
*/
|
||||
#define TOUCHGFX_BAREMETAL 1
|
||||
#define TOUCHGFX_FREERTOS 0
|
||||
|
||||
#endif // TOUCHGFX_CONFIG_H
|
18
src/config/trace-config.h
Normal file
18
src/config/trace-config.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef TRACE_CONFIG_H
|
||||
#define TRACE_CONFIG_H
|
||||
|
||||
#include "stm32f7xx_hal.h" // "mcu/mcu.h" not working here!
|
||||
|
||||
extern "C" UART_HandleTypeDef huart1; // Defined in main.c
|
||||
|
||||
#define USE_PLATFORM_F7_DISCO_GCC_TRACE 1
|
||||
|
||||
#define TRACE_UART_NUMBER 0
|
||||
#define TRACE_UART_HANDLE huart1
|
||||
#define TRACE_UART_BAUD_RATE /* 115200, but given by STM32CubeMX tool configuration */
|
||||
#define TRACE_UART_USE_TX_DMA false
|
||||
#define TRACE_UART_CONSTRUCTOR_PARAMETERS TRACE_UART_NUMBER, &TRACE_UART_HANDLE, TRACE_UART_USE_TX_DMA
|
||||
|
||||
#define TRACE_ADD_CRLF_SEQU 0
|
||||
|
||||
#endif // TRACE_CONFIG_H
|
36
src/config/xf-config.h
Normal file
36
src/config/xf-config.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef XF_CONFIG_H
|
||||
#define XF_CONFIG_H
|
||||
|
||||
#include "config/xf-port-config.h"
|
||||
|
||||
#if (PORT_IDF_STM32CUBE != 0)
|
||||
#define USE_XF_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_DISPATCHER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_RESOURCE_FACTORY_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION 1
|
||||
#define USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_IDF_STM32CUBE_PORT_FUNCTIONS_IMPLEMENTATION 1
|
||||
|
||||
#include "default-idf/eventqueue-default.h"
|
||||
#ifdef __cplusplus
|
||||
using XFEventQueue = XFEventQueueDefault;
|
||||
#endif // __cplusplus
|
||||
#endif // PORT_IDF_STM32CUBE
|
||||
#if (PORT_STM32CUBE_CMSIS_FREERTOS != 0)
|
||||
#define USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION 1
|
||||
#define USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_IMPLEMENTATION 1
|
||||
|
||||
#define XFTHREAD_DEFAULT_STACK_SIZE 2048
|
||||
|
||||
#include "stm32cube-cmsis-freertos/eventqueue.h"
|
||||
#ifdef __cplusplus
|
||||
using XFEventQueue = XFEventQueuePort;
|
||||
#endif // __cplusplus
|
||||
#endif // PORT_STM32CUBE_CMSIS_FREERTOS
|
||||
|
||||
#endif // XF_CONFIG_H
|
10
src/config/xf-port-config.h
Normal file
10
src/config/xf-port-config.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef XF_PORT_CONFIG_H
|
||||
#define XF_PORT_CONFIG_H
|
||||
|
||||
/**
|
||||
* Waring: Only one PORT define should be enabled at a time!
|
||||
*/
|
||||
#define PORT_IDF_STM32CUBE 1
|
||||
#define PORT_STM32CUBE_CMSIS_FREERTOS 0
|
||||
|
||||
#endif // XF_PORT_CONFIG_H
|
8
src/event/evbuttonirq.cpp
Normal file
8
src/event/evbuttonirq.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "events.h"
|
||||
#include "evbuttonirq.h"
|
||||
|
||||
evButtonIrq::evButtonIrq() :
|
||||
XFCustomEvent(evButtonIrqId)
|
||||
{
|
||||
setDeleteAfterConsume(false);
|
||||
}
|
13
src/event/evbuttonirq.h
Normal file
13
src/event/evbuttonirq.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef EVBUTTONIRQ_H
|
||||
#define EVBUTTONIRQ_H
|
||||
|
||||
#include "xf/customevent.h"
|
||||
#include "events.h"
|
||||
|
||||
class evButtonIrq : public XFCustomEvent
|
||||
{
|
||||
public:
|
||||
evButtonIrq();
|
||||
};
|
||||
|
||||
#endif // EVBUTTONIRQ_H
|
12
src/event/evbuttonpressed.cpp
Normal file
12
src/event/evbuttonpressed.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "events.h"
|
||||
#include "evbuttonpressed.h"
|
||||
|
||||
evButtonPressed::evButtonPressed(int buttonIndex) :
|
||||
XFCustomEvent(evButtonPressedId)
|
||||
{
|
||||
_buttonIndex = buttonIndex;
|
||||
}
|
||||
|
||||
uint16_t evButtonPressed::buttonIndex() {
|
||||
return _buttonIndex;
|
||||
}
|
18
src/event/evbuttonpressed.h
Normal file
18
src/event/evbuttonpressed.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef EVBUTTONPRESSED_H
|
||||
#define EVBUTTONPRESSED_H
|
||||
|
||||
#include "xf/customevent.h"
|
||||
#include "events.h"
|
||||
#include <stdint.h>
|
||||
|
||||
class evButtonPressed : public XFCustomEvent
|
||||
{
|
||||
public:
|
||||
evButtonPressed(int buttonIndex);
|
||||
uint16_t buttonIndex();
|
||||
private:
|
||||
uint16_t _buttonIndex;
|
||||
|
||||
};
|
||||
|
||||
#endif // EVBUTTONPRESSED_H
|
8
src/event/evbuttonreleased.cpp
Normal file
8
src/event/evbuttonreleased.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "events.h"
|
||||
#include "event/evbuttonreleased.h"
|
||||
|
||||
evButtonReleased::evButtonReleased() :
|
||||
XFCustomEvent(evButtonReleasedId)
|
||||
{
|
||||
|
||||
}
|
13
src/event/evbuttonreleased.h
Normal file
13
src/event/evbuttonreleased.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef EVBUTTONRELEASED_H
|
||||
#define EVBUTTONRELEASED_H
|
||||
|
||||
#include "xf/customevent.h"
|
||||
#include "events.h"
|
||||
|
||||
class evButtonReleased : public XFCustomEvent
|
||||
{
|
||||
public:
|
||||
evButtonReleased();
|
||||
};
|
||||
|
||||
#endif // EVBUTTONRELEASED_H
|
13
src/event/evcheckboxtrigger.cpp
Normal file
13
src/event/evcheckboxtrigger.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "events.h"
|
||||
#include "evcheckboxtrigger.h"
|
||||
|
||||
evCheckBoxTrigger::evCheckBoxTrigger(bool checked, int eventId) :
|
||||
XFCustomEvent(eventId),
|
||||
checked(checked)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool evCheckBoxTrigger::isChecked() const {
|
||||
return checked;
|
||||
}
|
17
src/event/evcheckboxtrigger.h
Normal file
17
src/event/evcheckboxtrigger.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef EV_CHECK_BOX_TRIGGER_H
|
||||
#define EV_CHECK_BOX_TRIGGER_H
|
||||
|
||||
#include "xf/customevent.h"
|
||||
#include "events.h"
|
||||
#include <stdint.h>
|
||||
|
||||
class evCheckBoxTrigger : public XFCustomEvent
|
||||
{
|
||||
public:
|
||||
evCheckBoxTrigger(bool checked, int eventId);
|
||||
bool isChecked() const;
|
||||
private:
|
||||
const bool checked;
|
||||
};
|
||||
|
||||
#endif // EV_CHECK_BOX_TRIGGER_H
|
12
src/event/events.h
Normal file
12
src/event/events.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef EVENTS_H
|
||||
#define EVENTS_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
evButtonIrqId = 1,
|
||||
evButtonPressedId,
|
||||
evButtonReleasedId
|
||||
|
||||
} EventIds;
|
||||
|
||||
#endif // EVENTS_H
|
53
src/mdw/ext-freqgen/frequencygenerator.cpp
Normal file
53
src/mdw/ext-freqgen/frequencygenerator.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "frequencygenerator.h"
|
||||
#include "trace/trace.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace external
|
||||
{
|
||||
|
||||
FrequencyGenerator* FrequencyGenerator::_instance = nullptr;
|
||||
FrequencyGenerator::FrequencyGenerator()
|
||||
{
|
||||
assert (_instance==nullptr);
|
||||
_instance = this;
|
||||
_mode = SINUS;
|
||||
_frequency = 500;
|
||||
_initialized = false;
|
||||
|
||||
}
|
||||
|
||||
void FrequencyGenerator::initialize() {
|
||||
if (Ext_FreqGen_Init() == 0)
|
||||
{
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void FrequencyGenerator::setWaveForm(f_mode mode) {
|
||||
_mode = mode;
|
||||
setGen();
|
||||
}
|
||||
|
||||
void FrequencyGenerator::setFrequency(uint32_t frequency) {
|
||||
_frequency = frequency;
|
||||
setGen();
|
||||
}
|
||||
|
||||
FrequencyGenerator* FrequencyGenerator::getInstance() {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
void FrequencyGenerator::setGen() {
|
||||
if (_initialized )
|
||||
{
|
||||
Ext_FreqGen_Set(_frequency, _mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace_out("Frequency Generator not initialized\n");
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace external */
|
||||
|
||||
|
34
src/mdw/ext-freqgen/frequencygenerator.h
Normal file
34
src/mdw/ext-freqgen/frequencygenerator.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef EXT_FREQGEN_FREQUENCYGENERATOR_H
|
||||
#define EXT_FREQGEN_FREQUENCYGENERATOR_H
|
||||
|
||||
#include "ext-26pin/ext_26pin.h"
|
||||
|
||||
namespace external
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief FrequencyGenerator class providing access to external frequency generator "MiniGen" module.
|
||||
*/
|
||||
class FrequencyGenerator
|
||||
{
|
||||
public:
|
||||
FrequencyGenerator();
|
||||
void initialize();
|
||||
void setWaveForm(f_mode mode);
|
||||
void setFrequency(uint32_t frequency);
|
||||
|
||||
public: //singleton
|
||||
static FrequencyGenerator* getInstance();
|
||||
|
||||
private: //methods
|
||||
void setGen();
|
||||
|
||||
private:
|
||||
uint32_t _frequency;
|
||||
f_mode _mode;
|
||||
bool _initialized;
|
||||
static FrequencyGenerator* _instance;
|
||||
};
|
||||
|
||||
} /* namespace external */
|
||||
#endif // EXT_FREQGEN_FREQUENCYGENERATOR_H
|
9
src/mdw/trace/CHANGELOG.md
Normal file
9
src/mdw/trace/CHANGELOG.md
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
## 0.1.1 - (2021-05-04)
|
||||
- Added mutex lock methods to `Trace` class
|
||||
|
||||
## 0.1.0 - (2019-04-25)
|
||||
- Moved project from SVN repository to GIT repository.
|
||||
Took code from ButtonManager project.
|
7
src/mdw/trace/README.md
Normal file
7
src/mdw/trace/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# trace
|
||||
|
||||
Trace package with interface definition.
|
||||
|
||||
The implementation of the Trace package is platform specific.
|
||||
|
||||
Every platform must provide its own implementation of the Trace package.
|
19
src/mdw/trace/config/trace-config.h
Normal file
19
src/mdw/trace/config/trace-config.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef TRACE_CONFIG_H
|
||||
#define TRACE_CONFIG_H
|
||||
|
||||
/**
|
||||
* Trace config example. Copy this file into the 'config' folder
|
||||
* of your project and do your configuration there.
|
||||
* Be sure to set up your include path such that the config file in
|
||||
* your project is seen first.
|
||||
*
|
||||
* Do not perform changes in this file at this location. It may
|
||||
* cause other projects to no more build!
|
||||
*/
|
||||
|
||||
#warning "No project specific trace configuration found! Taking default configuration!"
|
||||
|
||||
#define USE_TRACE_EXAMPLE 0
|
||||
#define TRACE_ADD_CRLF_SEQU 0
|
||||
|
||||
#endif // TRACE_CONFIG_H
|
2498
src/mdw/trace/doxygen/Doxyfile
Normal file
2498
src/mdw/trace/doxygen/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
39
src/mdw/trace/doxygen/trace.tag
Normal file
39
src/mdw/trace/doxygen/trace.tag
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||
<tagfile>
|
||||
<compound kind="class">
|
||||
<name>Trace</name>
|
||||
<filename>class_trace.html</filename>
|
||||
<member kind="function" static="yes">
|
||||
<type>static void</type>
|
||||
<name>initialize</name>
|
||||
<anchorfile>class_trace.html</anchorfile>
|
||||
<anchor>a6a42778d9401b9e90605475ecffeb8a2</anchor>
|
||||
<arglist>()</arglist>
|
||||
</member>
|
||||
<member kind="function" static="yes">
|
||||
<type>static void</type>
|
||||
<name>out</name>
|
||||
<anchorfile>class_trace.html</anchorfile>
|
||||
<anchor>a602aec03cad6466d892034582794de33</anchor>
|
||||
<arglist>(string str)</arglist>
|
||||
</member>
|
||||
<member kind="function" static="yes">
|
||||
<type>static void</type>
|
||||
<name>out</name>
|
||||
<anchorfile>class_trace.html</anchorfile>
|
||||
<anchor>a2c0dd29f5f94cfe01be01d414a2d18ba</anchor>
|
||||
<arglist>(const char *format,...)</arglist>
|
||||
</member>
|
||||
</compound>
|
||||
<compound kind="page">
|
||||
<name>index</name>
|
||||
<title>Trace</title>
|
||||
<filename>index</filename>
|
||||
<docanchor file="index" title="Introduction">sec_trace_intro</docanchor>
|
||||
<docanchor file="index" title="Targets">sec_trace_targets</docanchor>
|
||||
<docanchor file="index" title="Armebs4 Board">subsec_trace_armebs4</docanchor>
|
||||
<docanchor file="index" title="Serial Configuration">subsubsec_trace_f7_disco_serial_config</docanchor>
|
||||
<docanchor file="index" title="QT library">subsec_trace_qt</docanchor>
|
||||
<docanchor file="index" title="Links to related Documentation">sec_trace_external_links</docanchor>
|
||||
</compound>
|
||||
</tagfile>
|
15
src/mdw/trace/examples/trace-example01.cpp
Normal file
15
src/mdw/trace/examples/trace-example01.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "config/trace-config.h"
|
||||
#include "trace/trace.h"
|
||||
|
||||
#if (USE_TRACE_EXAMPLE != 0)
|
||||
|
||||
int main()
|
||||
{
|
||||
Trace::out("Hello World");
|
||||
|
||||
Trace::out("My name is %s and a am %d years old.", "Sarah Walker", 28);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // USE_TRACE_EXAMPLE
|
105
src/mdw/trace/trace.h
Normal file
105
src/mdw/trace/trace.h
Normal file
@ -0,0 +1,105 @@
|
||||
#ifndef TRACE_H
|
||||
#define TRACE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <config/trace-config.h> // angle brackets important here!
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void trace_initialize();
|
||||
void trace_out(const char * const format , ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/** \mainpage Trace
|
||||
*
|
||||
* \section sec_trace_intro Introduction
|
||||
*
|
||||
* This small library is used to print debug information to an output.
|
||||
* It serves as a general interface (LAL <b>L</b>ibrary <b>A</b>bstraction <b>L</b>ayer).
|
||||
*
|
||||
* The library consists of a single class named Trace. There is no need to make an instance
|
||||
* of this class. Instead use the #Trace::out() methods to output the information needed.
|
||||
*
|
||||
* \section sec_trace_targets Targets
|
||||
* \subsection subsec_trace_f7_disco F7-DISCO Board
|
||||
* When working with the F7-DISCO board, Trace outputs the information using the USB-STLINK interface
|
||||
* of the debugger USB cable to the Host. On Windows, the 'STLink Virtual COM' Port must be opened to
|
||||
* see the trace output.
|
||||
* During compilation time, the constant \a USE_PLATFORM_F7_DISCO_GCC_TRACE must be defined.
|
||||
* \subsubsection subsubsec_trace_f7_disco_serial_config Serial Configuration
|
||||
* - Baud: 115200
|
||||
* - Data Bits: 8
|
||||
* - Parity: none
|
||||
* - Stop Bits: 1
|
||||
* - Flow control: none
|
||||
*
|
||||
* \subsection subsec_trace_qt QT library
|
||||
* When working with the QT library, Trace outputs the information to the debuggers output window.
|
||||
* During compilation time, the constant \a TC_QTCREATOR must be defined.
|
||||
*
|
||||
* \section sec_trace_external_links Links to related Documentation
|
||||
* \if DOC_WITH_TESTBENCH
|
||||
* - <a href="../../../../../../test-bench/doxygen/output/html/index.html">Test Bench Documentation</a>
|
||||
* \endif
|
||||
* - <a href="../../../../../xf/doxygen/output/html/index.html">XF Documentation</a>
|
||||
*/
|
||||
|
||||
/**
|
||||
* \example trace-example01.cpp
|
||||
*/
|
||||
|
||||
/**
|
||||
* Prints debug information to a predefined output (output window).
|
||||
*/
|
||||
class Trace
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Initializes trace functionality.
|
||||
*
|
||||
* Call this method prior to use trace functionality.
|
||||
*/
|
||||
static void initialize();
|
||||
|
||||
/**
|
||||
* Outputs an STL string to the output window. The method will automatically add a new line, so
|
||||
* the next string will be put automatically on the next line in the output window.
|
||||
*
|
||||
* \param str String to print to the output window.
|
||||
*/
|
||||
static void out(string str);
|
||||
|
||||
/**
|
||||
* Outputs a sequence of data formatted as the fromat argument specifies.
|
||||
* This method can be used the same way as the traditional printf.
|
||||
* The method will automatically add a new line too.
|
||||
*
|
||||
* \param format The string that contains the text to be printed. It
|
||||
* can optionally contain embedded format specifiers that
|
||||
* are replaced by the values specified in subsequent additional
|
||||
* arguments and formatted as requested.
|
||||
*/
|
||||
static void out(const char * format, ...);
|
||||
|
||||
public:
|
||||
static void lock(); ///< Locks trace for other threads.
|
||||
static void unlock(); ///< Unlocks trace so other threads can access trace.
|
||||
|
||||
protected:
|
||||
Trace() {}
|
||||
};
|
||||
#endif // __cplusplus
|
||||
#endif // TRACE_H
|
1
src/platform/f7-disco-gcc/.gitignore
vendored
Normal file
1
src/platform/f7-disco-gcc/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.DS_Store
|
32
src/platform/f7-disco-gcc/CHANGELOG.md
Normal file
32
src/platform/f7-disco-gcc/CHANGELOG.md
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
## 0.2.7 - (2021-10-05)
|
||||
- Added class comments
|
||||
|
||||
## 0.2.6 - (2021-08-25)
|
||||
- Some minor bugfixes
|
||||
|
||||
## 0.2.5 - (2021-05-04)
|
||||
- Moved XF definitions into .cpp file
|
||||
|
||||
## 0.2.4 - (2021-05-04)
|
||||
- Added mutex to `Trace` and updated `TRACE_ADD_CRLF_SEQU` option
|
||||
- Added `ext-26pin` package
|
||||
|
||||
## 0.2.3 - (2020-03-27)
|
||||
- Added `main.h` file in different config files
|
||||
|
||||
## 0.2.2 - (2020-03-27)
|
||||
- Fixed include bug
|
||||
|
||||
## 0.2.1 - (2019-04-25)
|
||||
- Added BUTTONSCONTROLLER_EXCLUDE_FROM_BUILD define to exclude ButtonsController from build
|
||||
|
||||
## 0.2.0 - (2019-04-25)
|
||||
- Added ButtonsController class (originally from ButtonManager project)
|
||||
- Added C functions to trace package
|
||||
|
||||
## 0.1.0 - (2019-04-25)
|
||||
- Moved project from SVN repository to GIT repository.
|
||||
Took code from Realtime Oscilloscope project.
|
1
src/platform/f7-disco-gcc/README.md
Normal file
1
src/platform/f7-disco-gcc/README.md
Normal file
@ -0,0 +1 @@
|
||||
Project containing platform specific packages, based on the 32F746GDISCOVERY board
|
185
src/platform/f7-disco-gcc/board/buttonscontroller.cpp
Normal file
185
src/platform/f7-disco-gcc/board/buttonscontroller.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
#include <string.h>
|
||||
#include "mcu/mcu.h"
|
||||
#include "trace/trace.h"
|
||||
#include "buttonscontroller.h"
|
||||
#include "main.h"
|
||||
|
||||
#if !defined(BUTTONSCONTROLLER_EXCLUDE_FROM_BUILD) || defined(BUTTONSCONTROLLER_EXCLUDE_FROM_BUILD) && (BUTTONSCONTROLLER_EXCLUDE_FROM_BUILD == 0)
|
||||
|
||||
#ifndef BUTTONSCONTROLLER_DEBOUNCE_TIME
|
||||
#define BUTTONSCONTROLLER_DEBOUNCE_TIME 50 /* in milliseconds */
|
||||
#endif
|
||||
|
||||
#include "event/evbuttonirq.h"
|
||||
|
||||
ButtonsController * ButtonsController::_pInstance(nullptr);
|
||||
|
||||
ButtonsController::ButtonsController()
|
||||
{
|
||||
assert(!_pInstance); // Singleton pattern. Only one instance allowed.
|
||||
_pInstance = this; // Store 'this' to static pointer
|
||||
|
||||
_currentState = STATE_UNKOWN;
|
||||
|
||||
// Now the actual state of the buttons can be read
|
||||
_currentButtonsValue = readButtonsValue();
|
||||
|
||||
_callbacksCount = 0;
|
||||
}
|
||||
|
||||
ButtonsController::~ButtonsController()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ButtonsController::onIrq()
|
||||
{
|
||||
static evButtonIrq evButtonIrq;
|
||||
|
||||
pushEvent(&evButtonIrq, true);
|
||||
}
|
||||
|
||||
bool ButtonsController::registerCallback(interface::ButtonsControllerCallbackProvider * callbackProvider,
|
||||
interface::ButtonsControllerCallbackProvider::CallbackMethod callbackMethod)
|
||||
{
|
||||
if (_callbacksCount < MAX_CALLBACKS)
|
||||
{
|
||||
for (uint8_t i = 0; i < MAX_CALLBACKS; i++)
|
||||
{
|
||||
if (_callbackProvider[i].first == nullptr)
|
||||
{
|
||||
_callbackProvider[i].first = callbackProvider;
|
||||
_callbackProvider[i].second = callbackMethod;
|
||||
_callbacksCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ButtonsController::tButtonsValue ButtonsController::readButtonsValue()
|
||||
{
|
||||
tButtonsValue value = 0;
|
||||
|
||||
// Button BTN0
|
||||
value |= (HAL_GPIO_ReadPin(BUTTON0_GPIO_Port, BUTTON0_Pin) == GPIO_PIN_SET) ? 0x01 : 0x00;
|
||||
|
||||
// Button BTN1
|
||||
value |= (HAL_GPIO_ReadPin(BUTTON1_GPIO_Port, BUTTON1_Pin) == GPIO_PIN_SET) ? 0x02 : 0x00;
|
||||
|
||||
// Button BTN2
|
||||
value |= (HAL_GPIO_ReadPin(BUTTON2_GPIO_Port, BUTTON2_Pin) == GPIO_PIN_SET) ? 0x04 : 0x00;
|
||||
|
||||
// Button BTN3
|
||||
value |= (HAL_GPIO_ReadPin(BUTTON3_GPIO_Port, BUTTON3_Pin) == GPIO_PIN_SET) ? 0x08 : 0x00;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
XFEventStatus ButtonsController::processEvent()
|
||||
{
|
||||
eMainState newState = _currentState;
|
||||
|
||||
// Handle transition changes
|
||||
switch (_currentState)
|
||||
{
|
||||
case STATE_UNKOWN:
|
||||
// Decouple caller of startBehavior() with
|
||||
// the transition from UNKNOWN to INITIAL.
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::Initial)
|
||||
{
|
||||
newState = STATE_INITIAL;
|
||||
}
|
||||
break;
|
||||
case STATE_INITIAL:
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::NullTransition)
|
||||
{
|
||||
newState = STATE_CHECK_BUTTONS;
|
||||
}
|
||||
break;
|
||||
case STATE_CHECK_BUTTONS:
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::Event &&
|
||||
getCurrentEvent()->getId() == evButtonIrqId)
|
||||
{
|
||||
newState = STATE_DEBOUNCE;
|
||||
}
|
||||
break;
|
||||
case STATE_DEBOUNCE:
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::Timeout &&
|
||||
getCurrentTimeout()->getId() == Timeout_DEBOUNCE_id)
|
||||
{
|
||||
newState = STATE_CHECK_BUTTONS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Handle transitions
|
||||
if (_currentState != newState)
|
||||
{
|
||||
switch (newState)
|
||||
{
|
||||
case STATE_INITIAL:
|
||||
GEN(XFNullTransition());
|
||||
break;
|
||||
case STATE_CHECK_BUTTONS:
|
||||
|
||||
doCheckButtons();
|
||||
|
||||
break;
|
||||
case STATE_DEBOUNCE:
|
||||
scheduleTimeout(Timeout_DEBOUNCE_id, BUTTONSCONTROLLER_DEBOUNCE_TIME);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_currentState = newState;
|
||||
}
|
||||
return XFEventStatus::Consumed;
|
||||
}
|
||||
|
||||
|
||||
void ButtonsController::doCheckButtons()
|
||||
{
|
||||
tButtonsValue newButtonsValue = readButtonsValue();
|
||||
uint8_t mask = 0x01;
|
||||
|
||||
if (_currentButtonsValue != newButtonsValue)
|
||||
{
|
||||
for (uint32_t i = 0; i < BUTTONS_COUNT; i++)
|
||||
{
|
||||
if ((_currentButtonsValue & mask) != (newButtonsValue & mask))
|
||||
{
|
||||
notifyButtonChange(i, !(newButtonsValue & mask));
|
||||
}
|
||||
|
||||
mask <<= 0x01;
|
||||
}
|
||||
|
||||
_currentButtonsValue = newButtonsValue;
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonsController::notifyButtonChange(uint16_t buttonIndex, bool pressed)
|
||||
{
|
||||
#if (TRACE_BUTTONSCONTROLLER_NOTIFICATIONS != 0)
|
||||
Trace::out("Button %d %s", buttonIndex, (pressed) ? "pressed" : "released");
|
||||
#endif
|
||||
|
||||
for (uint8_t i = 0; i < MAX_CALLBACKS; i++)
|
||||
{
|
||||
if (_callbackProvider[i].first != nullptr)
|
||||
{
|
||||
(_callbackProvider[i].first->*_callbackProvider[i].second)(buttonIndex, pressed);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BUTTONSCONTROLLER_EXCLUDE_FROM_BUILD
|
90
src/platform/f7-disco-gcc/board/buttonscontroller.h
Normal file
90
src/platform/f7-disco-gcc/board/buttonscontroller.h
Normal file
@ -0,0 +1,90 @@
|
||||
#ifndef BOARD_BUTTONSCONTROLLER_H
|
||||
#define BOARD_BUTTONSCONTROLLER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <config/buttonscontroller-config.h>
|
||||
#if !defined(BUTTONSCONTROLLER_EXCLUDE_FROM_BUILD) || defined(BUTTONSCONTROLLER_EXCLUDE_FROM_BUILD) && (BUTTONSCONTROLLER_EXCLUDE_FROM_BUILD == 0)
|
||||
#include "interface/buttonirq.h"
|
||||
#include "xf/behavior.h"
|
||||
#include "interface/buttonscontrollercallbackcaller.h"
|
||||
|
||||
/**
|
||||
* @brief ButtonsController handles/generates button pressed- and released pressed events.
|
||||
*
|
||||
* Use the registerCallback() method to get informed about button pressed- and released events.
|
||||
*/
|
||||
class ButtonsController : protected interface::ButtonIrq,
|
||||
public interface::ButtonsControllerCallbackCaller,
|
||||
protected XFBehavior
|
||||
{
|
||||
friend void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
|
||||
public:
|
||||
typedef uint8_t tButtonsValue; ///< Type used to store the state of buttons.
|
||||
typedef std::pair<interface::ButtonsControllerCallbackProvider *,
|
||||
interface::ButtonsControllerCallbackProvider::CallbackMethod> CallbackProvider;
|
||||
|
||||
ButtonsController();
|
||||
virtual ~ButtonsController();
|
||||
|
||||
static ButtonsController & getInstance() { assert(_pInstance); return *_pInstance; } ///< Access to single instance
|
||||
|
||||
inline void start() { startBehavior(); }
|
||||
|
||||
tButtonsValue readButtonsValue(); ///< @brief Reads the actual state of the buttons.
|
||||
|
||||
protected:
|
||||
void onIrq() override;
|
||||
|
||||
public:
|
||||
bool registerCallback(interface::ButtonsControllerCallbackProvider * callbackProvider,
|
||||
interface::ButtonsControllerCallbackProvider::CallbackMethod callbackMethod) override;
|
||||
|
||||
public:
|
||||
XFEventStatus processEvent() override;
|
||||
|
||||
// Methods executed in state-machine
|
||||
protected:
|
||||
void doCheckButtons();
|
||||
|
||||
protected:
|
||||
void notifyButtonChange(uint16_t buttonIndex, bool pressed);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Timeout identifier(s) for this state machine
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
Timeout_DEBOUNCE_id = 1 ///< Timeout id for WAIT
|
||||
} eTimeoutId;
|
||||
|
||||
/**
|
||||
* Enumeration used to have a unique identifier for every
|
||||
* state in the state machine.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
STATE_UNKOWN = 0, ///< Unknown state
|
||||
STATE_INITIAL = 1, ///< Initial state
|
||||
STATE_CHECK_BUTTONS = 2, ///< Check state of buttons
|
||||
STATE_DEBOUNCE = 3 ///< Debounce state
|
||||
} eMainState;
|
||||
|
||||
eMainState _currentState; ///< Attribute indicating currently active state.
|
||||
|
||||
public:
|
||||
static constexpr const uint8_t BUTTONS_COUNT = 4; ///< Amount of buttons available.
|
||||
|
||||
protected:
|
||||
static ButtonsController * _pInstance;
|
||||
|
||||
tButtonsValue _currentButtonsValue; ///< Last read buttons state.
|
||||
|
||||
static constexpr const uint8_t MAX_CALLBACKS = 8;
|
||||
uint8_t _callbacksCount; ///< Stores how many callbacks are registered.
|
||||
CallbackProvider _callbackProvider[MAX_CALLBACKS]; ///< Registered callback providers.
|
||||
};
|
||||
|
||||
#endif // BUTTONSCONTROLLER_EXCLUDE_FROM_BUILD
|
||||
#endif // BOARD_BUTTONSCONTROLLER_H
|
27
src/platform/f7-disco-gcc/board/interface/buttonirq.h
Normal file
27
src/platform/f7-disco-gcc/board/interface/buttonirq.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef INTERFACE_BUTTONIRQ_H
|
||||
#define INTERFACE_BUTTONIRQ_H
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface needed by the Interrupt Service Routine (ISR).
|
||||
*
|
||||
* This interface is needed by the ISR which reacts on button
|
||||
* changes (level changes on GPIOs).
|
||||
*
|
||||
* Every time a level change on the buttons GPIOs is detected,
|
||||
* the ISR calls this method.
|
||||
*/
|
||||
class ButtonIrq
|
||||
{
|
||||
protected:
|
||||
virtual ~ButtonIrq() {}
|
||||
|
||||
virtual void onIrq() = 0; ///< @brief Called by the ISR.
|
||||
|
||||
protected:
|
||||
ButtonIrq() {} ///< Not allowing to instantiate object of interface.
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // INTERFACE_BUTTONIRQ_H
|
@ -0,0 +1,30 @@
|
||||
#ifndef INTERFACE_BUTTONS_CONTROLLER_CALLBACK_CALLER_H
|
||||
#define INTERFACE_BUTTONS_CONTROLLER_CALLBACK_CALLER_H
|
||||
|
||||
#include "buttonscontrollercallbackprovider.h"
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface to be provided by the ButtonsController.
|
||||
*
|
||||
*/
|
||||
class ButtonsControllerCallbackCaller
|
||||
{
|
||||
protected:
|
||||
virtual ~ButtonsControllerCallbackCaller() {}
|
||||
|
||||
/**
|
||||
* @brief Registers a callback method with its called pointer (callback provider).
|
||||
*
|
||||
* @return Returns true of the callback provider could be registered, otherwise false.
|
||||
*/
|
||||
virtual bool registerCallback(ButtonsControllerCallbackProvider * callbackProvider,
|
||||
ButtonsControllerCallbackProvider::CallbackMethod callbackMethod) = 0;
|
||||
|
||||
protected:
|
||||
ButtonsControllerCallbackCaller() {} ///< Not allowing to instantiate object of interface.
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // INTERFACE_BUTTONS_CONTROLLER_CALLBACK_CALLER_H
|
@ -0,0 +1,31 @@
|
||||
#ifndef INTERFACE_BUTTONS_CONTROLLER_CALLBACK_PROVIDER_H
|
||||
#define INTERFACE_BUTTONS_CONTROLLER_CALLBACK_PROVIDER_H
|
||||
|
||||
#include <stdint.h>
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface needed by the ButtonsController to notify a method callback provider.
|
||||
*
|
||||
*/
|
||||
class ButtonsControllerCallbackProvider
|
||||
{
|
||||
public:
|
||||
virtual ~ButtonsControllerCallbackProvider() {}
|
||||
|
||||
/**
|
||||
* @brief The method prototype of the callback method to be provided by the class implementing the interface.
|
||||
*
|
||||
* Example implementation:
|
||||
* // Called by ButtonsController to notify button pressed/released events.
|
||||
* void onButtonChanged(uint16_t buttonIndex, bool pressed);
|
||||
*
|
||||
*/
|
||||
typedef void (ButtonsControllerCallbackProvider::*CallbackMethod)(uint16_t buttonIndex, bool pressed);
|
||||
|
||||
protected:
|
||||
ButtonsControllerCallbackProvider() {} ///< Not allowing to instantiate object of interface.
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // INTERFACE_BUTTONS_CONTROLLER_CALLBACK_H
|
145
src/platform/f7-disco-gcc/board/ledcontroller.cpp
Normal file
145
src/platform/f7-disco-gcc/board/ledcontroller.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
#include "mcu/mcu.h"
|
||||
#include "config/ledcontroller-config.h"
|
||||
#if (LEDCONTROLLER_TRACE_ENABLE != 0)
|
||||
#include "trace/trace.h"
|
||||
#endif // LEDCONTROLLER_TRACE_ENABLE
|
||||
#include "ledcontroller.h"
|
||||
|
||||
LedController * LedController::_pInstance = nullptr;
|
||||
|
||||
LedController::LedController()
|
||||
{
|
||||
assert(!_pInstance); // Only one instance of this class allowed!
|
||||
_pInstance = this;
|
||||
|
||||
// Initialize the method array with the right methods.
|
||||
_ledOperation[0] = &LedController::setLed0;
|
||||
_ledOperation[1] = &LedController::setLed1;
|
||||
_ledOperation[2] = &LedController::setLed2;
|
||||
_ledOperation[3] = &LedController::setLed3;
|
||||
|
||||
/*
|
||||
* F7-DISCO LED GPIOs (Extension Board):
|
||||
* LED0: PA15
|
||||
* LED1: PH6
|
||||
* LED2: PA8
|
||||
* LED3: PB4
|
||||
*/
|
||||
}
|
||||
|
||||
LedController::~LedController()
|
||||
{
|
||||
}
|
||||
|
||||
void LedController::setLed(uint8_t index, bool bOn)
|
||||
{
|
||||
setLeds(0x01 << index, bOn);
|
||||
}
|
||||
|
||||
void LedController::setLeds(uint8_t ledMask, bool bOn)
|
||||
{
|
||||
uint8_t mask = 0x01;
|
||||
|
||||
for (uint8_t i = 0; i < ledCount(); i++, mask <<= 1)
|
||||
{
|
||||
if ((ledMask & mask) == mask && _ledOperation[i])
|
||||
{
|
||||
(this->*_ledOperation[i])(bOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LedController::setLed0(bool bOn /* = true */)
|
||||
{
|
||||
if (bOn)
|
||||
{
|
||||
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
#if (LEDCONTROLLER_TRACE_ENABLE != 0)
|
||||
if (bOn)
|
||||
{
|
||||
// Not using "%s" here (bug in gcc c-library!)
|
||||
Trace::out(" LED0: on");
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace::out(" LED0: off");
|
||||
}
|
||||
#endif // LEDCONTROLLER_TRACE_ENABLE
|
||||
}
|
||||
|
||||
void LedController::setLed1(bool bOn /* = true */)
|
||||
{
|
||||
if (bOn)
|
||||
{
|
||||
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
#if (LEDCONTROLLER_TRACE_ENABLE != 0)
|
||||
if (bOn)
|
||||
{
|
||||
Trace::out(" LED1: on");
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace::out(" LED1: off");
|
||||
}
|
||||
#endif // LEDCONTROLLER_TRACE_ENABLE
|
||||
}
|
||||
|
||||
void LedController::setLed2(bool bOn /* = true */)
|
||||
{
|
||||
if (bOn)
|
||||
{
|
||||
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
#if (LEDCONTROLLER_TRACE_ENABLE != 0)
|
||||
if (bOn)
|
||||
{
|
||||
Trace::out(" LED2: on");
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace::out(" LED2: off");
|
||||
}
|
||||
#endif // LEDCONTROLLER_TRACE_ENABLE
|
||||
}
|
||||
|
||||
void LedController::setLed3(bool bOn /* = true */)
|
||||
{
|
||||
if (bOn)
|
||||
{
|
||||
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
#if (LEDCONTROLLER_TRACE_ENABLE != 0)
|
||||
if (bOn)
|
||||
{
|
||||
Trace::out(" LED3: on");
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace::out(" LED3: off");
|
||||
}
|
||||
#endif // LEDCONTROLLER_TRACE_ENABLE
|
||||
}
|
40
src/platform/f7-disco-gcc/board/ledcontroller.h
Normal file
40
src/platform/f7-disco-gcc/board/ledcontroller.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef BOARD_LEDCONTROLLER_H
|
||||
#define BOARD_LEDCONTROLLER_H
|
||||
|
||||
#include <cassert>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Used to command LEDs on the F7-DISCO extension board.
|
||||
*/
|
||||
class LedController
|
||||
{
|
||||
public:
|
||||
#define LED_COUNT 4
|
||||
|
||||
public:
|
||||
LedController();
|
||||
virtual ~LedController();
|
||||
|
||||
inline static LedController & getInstance() { assert(_pInstance); return *_pInstance; }
|
||||
|
||||
void setLed(uint8_t index, bool bOn = true);
|
||||
void setLeds(uint8_t ledMask, bool bOn = true);
|
||||
|
||||
inline uint8_t ledCount() const { return LED_COUNT; }
|
||||
|
||||
void setLed0(bool bOn = true);
|
||||
void setLed1(bool bOn = true);
|
||||
void setLed2(bool bOn = true);
|
||||
void setLed3(bool bOn = true);
|
||||
|
||||
protected:
|
||||
typedef void (LedController::*ledMethod)(bool bOn); ///< Function prototype to led operation. Used for fast access to LED operation.
|
||||
|
||||
protected:
|
||||
static LedController * _pInstance;
|
||||
|
||||
ledMethod _ledOperation[LED_COUNT]; ///< Array of pointers to led functions.
|
||||
};
|
||||
|
||||
#endif // BOARD_LEDCONTROLLER_H
|
149
src/platform/f7-disco-gcc/board/trace.cpp
Normal file
149
src/platform/f7-disco-gcc/board/trace.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
#include <config/trace-config.h>
|
||||
|
||||
#if (USE_PLATFORM_F7_DISCO_GCC_TRACE != 0)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hal/uart.h"
|
||||
#include "trace/trace.h" // Include the general trace.h file (common for many projects)
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
|
||||
#ifndef TRACE_ADD_CRLF_SEQU
|
||||
#define TRACE_ADD_CRLF_SEQU 0
|
||||
#endif
|
||||
|
||||
using interface::XFResourceFactory;
|
||||
using interface::XFMutex;
|
||||
|
||||
static Uart traceUart(TRACE_UART_CONSTRUCTOR_PARAMETERS);
|
||||
static char strTrace[255];
|
||||
|
||||
static int32_t checkStringEnding(char * str, uint32_t len);
|
||||
|
||||
static interface::XFMutex & traceMutex()
|
||||
{
|
||||
static XFMutex * mutex = XFResourceFactory::getInstance()->createMutex();
|
||||
return *mutex;
|
||||
}
|
||||
|
||||
static void traceMutexLock()
|
||||
{
|
||||
traceMutex().lock();
|
||||
}
|
||||
|
||||
static void traceMutexUnlock()
|
||||
{
|
||||
traceMutex().unlock();
|
||||
}
|
||||
|
||||
void trace_initialize()
|
||||
{
|
||||
Trace::initialize();
|
||||
}
|
||||
|
||||
void trace_out(const char * const format , ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
// Format string
|
||||
va_start(args, format);
|
||||
vsprintf(strTrace, format, args);
|
||||
va_end(args);
|
||||
|
||||
checkStringEnding(strTrace, strlen(strTrace));
|
||||
|
||||
traceUart.write(strTrace);
|
||||
}
|
||||
|
||||
//static
|
||||
void Trace::initialize()
|
||||
{
|
||||
traceUart.initialize(TRACE_UART_BAUD_RATE);
|
||||
}
|
||||
|
||||
static int32_t checkStringEnding(char * str, uint32_t len)
|
||||
{
|
||||
if (!len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (str[len-1] != '\n')
|
||||
{
|
||||
#if (TRACE_ADD_CRLF_SEQU != 0)
|
||||
// Add "\r\n" at the end of the string
|
||||
str[len] = '\r';
|
||||
str[len+1] = '\n';
|
||||
str[len+2] = '\0';
|
||||
#else
|
||||
// Add "\n" at the end of the string
|
||||
str[len] = '\n';
|
||||
str[len+1] = '\0';
|
||||
#endif // TRACE_ADD_CRLF_SEQU
|
||||
}
|
||||
#if (TRACE_ADD_CRLF_SEQU != 0)
|
||||
// Check string finishing with "\r\n"
|
||||
else if (str[len-1] == '\n')
|
||||
{
|
||||
// Check if second last char is an '\r'
|
||||
if (len == 1 ||
|
||||
(len >= 2 && str[len-2] != '\r'))
|
||||
{
|
||||
// Squeeze a '\r'
|
||||
memmove(&str[len], &str[len-1], 2);
|
||||
str[len-1] = '\r';
|
||||
}
|
||||
}
|
||||
#endif // TRACE_ADD_CRLF_SEQU
|
||||
return strlen(str);
|
||||
}
|
||||
|
||||
void Trace::out(string str)
|
||||
{
|
||||
traceMutexLock();
|
||||
if (str[str.length()-1] != '\n')
|
||||
{
|
||||
str += '\n';
|
||||
}
|
||||
|
||||
#if defined(TRACE_ADD_CRLF_SEQU) && (TRACE_ADD_CRLF_SEQU != 0)
|
||||
if(str[str.length()-2] != '\r'){
|
||||
str.insert(str.length()-1, "\r");
|
||||
}
|
||||
#endif // TRACE_ADD_CRLF_SEQU
|
||||
|
||||
traceUart.write(str.data(), str.length());
|
||||
traceMutexUnlock();
|
||||
}
|
||||
|
||||
void Trace::out(const char * format, ...)
|
||||
{
|
||||
traceMutexLock();
|
||||
va_list args;
|
||||
|
||||
// Format string
|
||||
va_start(args, format);
|
||||
vsprintf(strTrace, format, args);
|
||||
va_end(args);
|
||||
|
||||
checkStringEnding(strTrace, strlen(strTrace));
|
||||
|
||||
traceUart.write(strTrace);
|
||||
traceMutexUnlock();
|
||||
}
|
||||
|
||||
//static
|
||||
void Trace::lock()
|
||||
{
|
||||
traceMutexLock();
|
||||
}
|
||||
|
||||
//static
|
||||
void Trace::unlock()
|
||||
{
|
||||
traceMutexUnlock();
|
||||
}
|
||||
|
||||
#endif // USE_PLATFORM_F7_DISCO_GCC_TRACE
|
25
src/platform/f7-disco-gcc/config/buttonscontroller-config.h
Normal file
25
src/platform/f7-disco-gcc/config/buttonscontroller-config.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef BOARD_BUTTONSCONTROLLER_CONFIG_H
|
||||
#define BOARD_BUTTONSCONTROLLER_CONFIG_H
|
||||
|
||||
/**
|
||||
* Do NOT edit this file!
|
||||
*
|
||||
* This is the default ButtonsController config file.
|
||||
* You may provide your own implementation at project level.
|
||||
*
|
||||
* For this:
|
||||
* - Copy/paste this file into a folder named 'config' in
|
||||
* you projects include/source directory.
|
||||
* - Add a compiler include path so that your file is seen
|
||||
* before the default config file provided in the platform
|
||||
* package.
|
||||
* - Adjust the content of your config file to your needs.
|
||||
* - Remove this comment in your config file.
|
||||
*/
|
||||
|
||||
#include "main.h" // To get GPIO user labels (BUTTON0, BUTTON1, etc.)
|
||||
|
||||
#define BUTTONSCONTROLLER_EXCLUDE_FROM_BUILD 0 /* Default: 0 */
|
||||
#define TRACE_BUTTONSCONTROLLER_NOTIFICATIONS 0
|
||||
|
||||
#endif // BOARD_BUTTONSCONTROLLER_CONFIG_H
|
24
src/platform/f7-disco-gcc/config/ledcontroller-config.h
Normal file
24
src/platform/f7-disco-gcc/config/ledcontroller-config.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef BOARD_LEDCONTROLLER_CONFIG_H
|
||||
#define BOARD_LEDCONTROLLER_CONFIG_H
|
||||
|
||||
/**
|
||||
* Do NOT edit this file!
|
||||
*
|
||||
* This is the default LedController config file.
|
||||
* You may provide your own implementation at project level.
|
||||
*
|
||||
* For this:
|
||||
* - Copy/paste this file into a folder named 'config' in
|
||||
* you projects include/source directory.
|
||||
* - Add a compiler include path so that your file is seen
|
||||
* before the default config file provided in the platform
|
||||
* package.
|
||||
* - Adjust the content of your config file to your needs.
|
||||
* - Remove this comment in your config file.
|
||||
*/
|
||||
|
||||
#include "main.h" // To get GPIO user labels (LED0, LED1, etc.)
|
||||
|
||||
#define LEDCONTROLLER_TRACE_ENABLE 1
|
||||
|
||||
#endif // BOARD_LEDCONTROLLER_CONFIG_H
|
34
src/platform/f7-disco-gcc/config/trace-config.h
Normal file
34
src/platform/f7-disco-gcc/config/trace-config.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef TRACE_CONFIG_H
|
||||
#define TRACE_CONFIG_H
|
||||
|
||||
/**
|
||||
* Do NOT edit this file!
|
||||
*
|
||||
* This is the default TRACE config file.
|
||||
* You may provide your own implementation at project level.
|
||||
*
|
||||
* For this:
|
||||
* - Copy/paste this file into a folder named 'config' in
|
||||
* you projects include/source directory.
|
||||
* - Add a compiler include path so that your file is seen
|
||||
* before the default config file provided in the platform
|
||||
* package.
|
||||
* - Adjust the content of your config file to your needs.
|
||||
* - Remove this comment in your config file.
|
||||
*/
|
||||
|
||||
#include "stm32f7xx_hal.h" // Do not use "mcu/mcu.h" here!
|
||||
|
||||
extern "C" UART_HandleTypeDef huart1; // Defined in main.c
|
||||
|
||||
#define USE_PLATFORM_F7_DISCO_GCC_TRACE 1
|
||||
|
||||
#define TRACE_UART_NUMBER 0
|
||||
#define TRACE_UART_HANDLE huart1
|
||||
#define TRACE_UART_BAUD_RATE /* 115200, but given by STM32CubeMX tool configuration */
|
||||
#define TRACE_UART_USE_TX_DMA false
|
||||
#define TRACE_UART_CONSTRUCTOR_PARAMETERS TRACE_UART_NUMBER, &TRACE_UART_HANDLE, TRACE_UART_USE_TX_DMA
|
||||
|
||||
#define TRACE_ADD_CRLF_SEQU 1
|
||||
|
||||
#endif // TRACE_CONFIG_H
|
22
src/platform/f7-disco-gcc/config/uart-config.h
Normal file
22
src/platform/f7-disco-gcc/config/uart-config.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef HAL_UART_CONFIG_H
|
||||
#define HAL_UART_CONFIG_H
|
||||
|
||||
/**
|
||||
* Do NOT edit this file!
|
||||
*
|
||||
* This is the default UART config file.
|
||||
* You may provide your own implementation at project level.
|
||||
*
|
||||
* For this:
|
||||
* - Copy/paste this file into a folder named 'config' in
|
||||
* you projects include/source directory.
|
||||
* - Add a compiler include path so that your file is seen
|
||||
* before the default config file provided in the platform
|
||||
* package.
|
||||
* - Adjust the content of your config file to your needs.
|
||||
* - Remove this comment in your config file.
|
||||
*/
|
||||
|
||||
#include "mcu/mcu.h"
|
||||
|
||||
#endif // HAL_UART_CONFIG_H
|
135
src/platform/f7-disco-gcc/ext-26pin/ext_26pin.c
Normal file
135
src/platform/f7-disco-gcc/ext-26pin/ext_26pin.c
Normal file
@ -0,0 +1,135 @@
|
||||
|
||||
#include "stm32f7xx_hal.h"
|
||||
#include "ext_26pin.h"
|
||||
|
||||
extern SPI_HandleTypeDef hspi2;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
int32_t Ext_Debug_Init (void) {
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOF_CLK_ENABLE();
|
||||
|
||||
/* Configure GPIO pin: PF9 (GPIO_DEBUG) */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_9;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
|
||||
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
int32_t Ext_FreqGen_Init (void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOF_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOI_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(nCS_FREQ_GEN_GPIO_Port, nCS_FREQ_GEN_Pin, GPIO_PIN_SET);
|
||||
|
||||
/*Configure GPIO pin : nCS_FREQ_GEN_Pin */
|
||||
GPIO_InitStruct.Pin = nCS_FREQ_GEN_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(nCS_FREQ_GEN_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
|
||||
__HAL_RCC_SPI2_CLK_ENABLE();
|
||||
|
||||
/**SPI2 GPIO Configuration
|
||||
PI1 ------> SPI2_SCK
|
||||
PB15 ------> SPI2_MOSI
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_1;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
|
||||
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_15;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
|
||||
/* SPI2 parameter configuration*/
|
||||
hspi2.Instance = SPI2;
|
||||
hspi2.Init.Mode = SPI_MODE_MASTER;
|
||||
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
|
||||
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
|
||||
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
|
||||
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||
hspi2.Init.NSS = SPI_NSS_SOFT;
|
||||
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
|
||||
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
|
||||
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
|
||||
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
|
||||
hspi2.Init.CRCPolynomial = 7;
|
||||
hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
|
||||
hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
|
||||
if (HAL_SPI_Init(&hspi2) != HAL_OK)
|
||||
return -1;
|
||||
Ext_FreqGen_Set(20,SQUARE);
|
||||
Ext_FreqGen_Set(20,SQUARE);
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
void Ext_FreqGen_Set(uint32_t frequency,f_mode mode)
|
||||
{
|
||||
uint8_t data[2];
|
||||
float calcDivisor;
|
||||
uint32_t divisorInt;
|
||||
calcDivisor = ((float)frequency * 268435456L) / 16000000L;
|
||||
divisorInt = (uint32_t)calcDivisor - 1;
|
||||
//----------------------------------------------------------------------------
|
||||
// reset generator
|
||||
data[0] = 0x21;
|
||||
data[1] = 0x00;
|
||||
HAL_GPIO_WritePin(nCS_FREQ_GEN_GPIO_Port, nCS_FREQ_GEN_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(&hspi2,data,2,10);
|
||||
HAL_GPIO_WritePin(nCS_FREQ_GEN_GPIO_Port, nCS_FREQ_GEN_Pin, GPIO_PIN_SET);
|
||||
//----------------------------------------------------------------------------
|
||||
// set frequency LSB (14 bits)
|
||||
data[0] = ((divisorInt & 0x3FFF) | 0x4000) >> 8;
|
||||
data[1] = ((divisorInt & 0x3FFF) | 0x4000) >> 0;
|
||||
HAL_GPIO_WritePin(nCS_FREQ_GEN_GPIO_Port, nCS_FREQ_GEN_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(&hspi2,data,2,10);
|
||||
HAL_GPIO_WritePin(nCS_FREQ_GEN_GPIO_Port, nCS_FREQ_GEN_Pin, GPIO_PIN_SET);
|
||||
//----------------------------------------------------------------------------
|
||||
// set frequency MSB (14 bits)
|
||||
data[0] = (((divisorInt>>14) & 0x3FFF) | 0x4000) >> 8;
|
||||
data[1] = (((divisorInt>>14) & 0x3FFF) | 0x4000) >> 0;
|
||||
HAL_GPIO_WritePin(nCS_FREQ_GEN_GPIO_Port, nCS_FREQ_GEN_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(&hspi2,data,2,10);
|
||||
HAL_GPIO_WritePin(nCS_FREQ_GEN_GPIO_Port, nCS_FREQ_GEN_Pin, GPIO_PIN_SET);
|
||||
//----------------------------------------------------------------------------
|
||||
// set output signal
|
||||
data[0] = 0x20; // unreset
|
||||
switch(mode)
|
||||
{
|
||||
case SINUS:
|
||||
data[1] = 0x00;
|
||||
break;
|
||||
case TRIANGLE:
|
||||
data[1] = 0x02;
|
||||
break;
|
||||
case SQUARE:
|
||||
data[1] = 0x28;
|
||||
break;
|
||||
}
|
||||
HAL_GPIO_WritePin(nCS_FREQ_GEN_GPIO_Port, nCS_FREQ_GEN_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(&hspi2,data,2,10);
|
||||
HAL_GPIO_WritePin(nCS_FREQ_GEN_GPIO_Port, nCS_FREQ_GEN_Pin, GPIO_PIN_SET);
|
||||
}
|
55
src/platform/f7-disco-gcc/ext-26pin/ext_26pin.h
Normal file
55
src/platform/f7-disco-gcc/ext-26pin/ext_26pin.h
Normal file
@ -0,0 +1,55 @@
|
||||
/************************************************************************//**
|
||||
* \file ext_keyboard.h
|
||||
* \brief Function to use the extension keyboard
|
||||
* \author pascal (dot) sartoretti (at) hevs (dot) ch
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef __EXT_26PIN_H
|
||||
#define __EXT_26PIN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "stm32f7xx_hal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define nCS_FREQ_GEN_Pin GPIO_PIN_6
|
||||
#define nCS_FREQ_GEN_GPIO_Port GPIOF
|
||||
typedef enum
|
||||
{
|
||||
SINUS,
|
||||
TRIANGLE,
|
||||
SQUARE
|
||||
}f_mode;
|
||||
/************************************************************************//**
|
||||
* \brief Inits the Sparkfun frequency generator connected to SPI
|
||||
* port on the 26 pin connector pins below:
|
||||
* SCK = pin 3
|
||||
* MOSI = pin 2
|
||||
* nCS = pin 4
|
||||
***************************************************************************/
|
||||
int32_t Ext_FreqGen_Init (void);
|
||||
/************************************************************************//**
|
||||
* \brief Sets a frequency on Sparfun generator output
|
||||
* \param frequency The frequency in hertz (below 20 Hz signal is bad)
|
||||
* \param mode The signal mode (SINUS,TRIANGLE,SQUARE)
|
||||
*
|
||||
* The signal is centered at about 1.61 volt +/- 0.53 volts
|
||||
***************************************************************************/
|
||||
void Ext_FreqGen_Set(uint32_t frequency,f_mode mode);
|
||||
|
||||
/************************************************************************//**
|
||||
* \brief Inits the debug pin PF9
|
||||
***************************************************************************/
|
||||
int32_t Ext_Debug_Init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __BOARD_LED_H */
|
||||
|
46
src/platform/f7-disco-gcc/mcu/critical/critical.cpp
Normal file
46
src/platform/f7-disco-gcc/mcu/critical/critical.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include "mcu/mcu.h"
|
||||
#include "critical.h"
|
||||
|
||||
static volatile int inIsr_ = 0;
|
||||
static volatile int enterCriticalNested_ = 0;
|
||||
|
||||
void critical_enter()
|
||||
{
|
||||
// Only disable interrupts when not calling from an ISR
|
||||
if (!critical_inIsr())
|
||||
{
|
||||
if (!enterCriticalNested_)
|
||||
{
|
||||
// Turn off the priority configurable interrupts
|
||||
__disable_irq();
|
||||
}
|
||||
enterCriticalNested_++;
|
||||
}
|
||||
}
|
||||
|
||||
void critical_exit()
|
||||
{
|
||||
// Only enable interrupts when not calling from an ISR
|
||||
if (!critical_inIsr())
|
||||
{
|
||||
enterCriticalNested_--;
|
||||
|
||||
if (!enterCriticalNested_)
|
||||
{
|
||||
// Turn on the interrupts with configurable priority
|
||||
__enable_irq();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int critical_inIsr()
|
||||
{
|
||||
// Variable must be put to TRUE in every ISR to indicate execution
|
||||
// of an ISR and need to put back to FALSE before leaving ISR.
|
||||
return inIsr_;
|
||||
}
|
||||
|
||||
void critical_setInIsr(bool inIsr)
|
||||
{
|
||||
inIsr_ = inIsr;
|
||||
}
|
20
src/platform/f7-disco-gcc/mcu/critical/critical.h
Normal file
20
src/platform/f7-disco-gcc/mcu/critical/critical.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef CRITICAL_H
|
||||
#define CRITICAL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void critical_enter(); ///< Disables all interrupts.
|
||||
void critical_exit(); ///< Enables all interrupts.
|
||||
|
||||
int critical_inIsr(); ///< Returns 1 if in an interrupt service routine (ISR), 0 otherwise.
|
||||
void critical_setInIsr(bool inIsr); ///< Set or clear 'bInISR' variable.
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CRITICAL_H */
|
93
src/platform/f7-disco-gcc/mcu/hal/uart.cpp
Normal file
93
src/platform/f7-disco-gcc/mcu/hal/uart.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include <string.h>
|
||||
#include "mcu/mcu.h"
|
||||
#include "uart.h"
|
||||
|
||||
#ifndef TRACE_UART_PREEMPTION_PRIO
|
||||
#define TRACE_UART_PREEMPTION_PRIO 0
|
||||
#endif
|
||||
|
||||
Uart * Uart::_sUart[Uart::UART_COUNT]; // Comment: Startup script should initialize pointers to zero (.bss section)
|
||||
bool Uart::_sInitialized[Uart::UART_COUNT]; // Same for other arrays
|
||||
|
||||
Uart::Uart(const unsigned char uartNbr, UART_HandleTypeDef * uartHandle, bool bTxDMA /* = false */)
|
||||
: _uartNbr(-1),
|
||||
_pUartHandle(NULL),
|
||||
_bTxDMA(bTxDMA)
|
||||
{
|
||||
assert(uartNbr < UART_COUNT);
|
||||
|
||||
if (uartNbr < UART_COUNT)
|
||||
{
|
||||
if (!_sUart[uartNbr])
|
||||
{
|
||||
// Register instance
|
||||
_sUart[uartNbr] = this;
|
||||
_uartNbr = uartNbr;
|
||||
|
||||
_pUartHandle = uartHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false); // Error: Instance for specified UART already exists.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Uart::~Uart()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Uart::initialize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Uart::enable()
|
||||
{
|
||||
// Enable the USART
|
||||
__HAL_UART_ENABLE(_pUartHandle);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Uart::disable()
|
||||
{
|
||||
// enable the USART
|
||||
__HAL_UART_DISABLE(_pUartHandle);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Uart::write(const char * str, unsigned int length /* = 0 */)
|
||||
{
|
||||
if (!length)
|
||||
{
|
||||
length = strlen(str);
|
||||
}
|
||||
|
||||
if (!_bTxDMA)
|
||||
{ // Transmit without DMA
|
||||
// Send next character
|
||||
HAL_UART_Transmit(_pUartHandle, (uint8_t *)str, length, 50);
|
||||
}
|
||||
else
|
||||
{ // TX DMA enabled
|
||||
writeUsingDMA((const uint8_t *)str, length);
|
||||
}
|
||||
}
|
||||
|
||||
void Uart::writeUsingDMA(const uint8_t * str, uint32_t length)
|
||||
{
|
||||
assert(length <= sizeof(_pTxDmaBuffer));
|
||||
|
||||
// Copy data to TX DMA buffer
|
||||
::memcpy(_pTxDmaBuffer, str, length);
|
||||
|
||||
// Check that a Tx process is not already ongoing
|
||||
// (should never happen, but who knows!)
|
||||
while (_pUartHandle->gState != HAL_UART_STATE_READY)
|
||||
{ continue; }
|
||||
|
||||
// Give data to TX DMA
|
||||
HAL_UART_Transmit_DMA(_pUartHandle, _pTxDmaBuffer, length);
|
||||
}
|
||||
|
66
src/platform/f7-disco-gcc/mcu/hal/uart.h
Normal file
66
src/platform/f7-disco-gcc/mcu/hal/uart.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef HAL_UART_H
|
||||
#define HAL_UART_H
|
||||
|
||||
#include "config/uart-config.h"
|
||||
#include "cassert"
|
||||
|
||||
#ifndef UART_TX_DMA_BUFFER_SIZE
|
||||
#define UART_TX_DMA_BUFFER_SIZE 128
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Provides general access to the microcontrollers UART peripheral.
|
||||
*/
|
||||
class Uart
|
||||
{
|
||||
friend class Factory;
|
||||
|
||||
public:
|
||||
Uart(const unsigned char uartNbr, UART_HandleTypeDef * uartHandle, bool bTxDMA = false);
|
||||
virtual ~Uart();
|
||||
|
||||
bool initialize();
|
||||
|
||||
bool enable();
|
||||
bool disable();
|
||||
|
||||
void write(const char * str, unsigned int length = 0);
|
||||
|
||||
|
||||
/**
|
||||
* Static accessor to the instances of UART. Used by the factory.
|
||||
* You should not use this method directly. Use the factory to
|
||||
* access an UART instead.
|
||||
*/
|
||||
static inline Uart & uart(const unsigned char uartNbr)
|
||||
{
|
||||
assert(uartNbr < UART_COUNT);
|
||||
return *_sUart[uartNbr];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if UART is present and initialized
|
||||
*/
|
||||
static inline bool present(const unsigned char uartNbr)
|
||||
{
|
||||
return (uartNbr < UART_COUNT &&
|
||||
_sInitialized[uartNbr]) ? true : false;
|
||||
}
|
||||
|
||||
protected:
|
||||
void writeUsingDMA(const uint8_t * str, uint32_t length);
|
||||
|
||||
protected:
|
||||
static const unsigned char UART_COUNT = 3; ///< Constant indicating how many USART the MCU has
|
||||
|
||||
unsigned char _uartNbr; ///< Number of UART. Index starting at 0
|
||||
UART_HandleTypeDef * _pUartHandle; ///< Reference to the USART structure
|
||||
|
||||
static Uart * _sUart[UART_COUNT]; ///< Array to check if USB device was created already
|
||||
static bool _sInitialized[UART_COUNT]; ///< Indicates if the UART has been initialized
|
||||
|
||||
const bool _bTxDMA; ///< Use DMA for transmission
|
||||
uint8_t _pTxDmaBuffer[UART_TX_DMA_BUFFER_SIZE]; ///< Buffer used by DMA for transmission
|
||||
};
|
||||
|
||||
#endif // HAL_UART_H
|
24
src/platform/f7-disco-gcc/mcu/mcu.h
Normal file
24
src/platform/f7-disco-gcc/mcu/mcu.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef MCU_STM32F7_MCU_H
|
||||
#define MCU_STM32F7_MCU_H
|
||||
|
||||
#include "stm32f7xx_hal.h"
|
||||
#include "trace/trace.h"
|
||||
|
||||
/**
|
||||
* @brief Static class representing the actual microcontroller (MCU).
|
||||
*/
|
||||
class Mcu
|
||||
{
|
||||
public:
|
||||
inline static void msleep(uint32_t msecs) { HAL_Delay(msecs); }
|
||||
inline static void wait() { for (uint32_t i = 1000000; i > 0; i--) continue; }
|
||||
static void reset()
|
||||
{
|
||||
Trace::out("Mcu: Reset");
|
||||
Trace::out("----------------------------------------------------");
|
||||
wait();
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // MCU_STM32F7_MCU_H
|
10
src/xf/config/xf-config.h
Normal file
10
src/xf/config/xf-config.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef XF_CONFIG_DEFAULT_H
|
||||
#define XF_CONFIG_DEFAULT_H
|
||||
|
||||
#warning "You should provide your own 'xf-config.h' file in your project!"
|
||||
|
||||
// If you need some inspiration on what to provide in the 'xf-config.h' file
|
||||
// please have a look onto the 'xf-config.h' files provided in the
|
||||
// XF test-bench tests.
|
||||
|
||||
#endif // XF_CONFIG_DEFAULT_H
|
104
src/xf/core/behavior.cpp
Normal file
104
src/xf/core/behavior.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#include <cassert>
|
||||
#include "xf/xf.h"
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "xf/interface/dispatcher.h"
|
||||
#include "xf/timeout.h"
|
||||
#include "xf/initialevent.h"
|
||||
#include "xf/behavior.h"
|
||||
|
||||
using interface::XFResourceFactory;
|
||||
|
||||
XFBehavior::XFBehavior(bool ownDispatcher /* = false */) :
|
||||
pDispatcher_(nullptr),
|
||||
hasOwnDispatcher_(ownDispatcher),
|
||||
deleteOnTerminate_(false),
|
||||
pCurrentEvent_(nullptr)
|
||||
{
|
||||
if (ownDispatcher)
|
||||
{
|
||||
pDispatcher_ = XFResourceFactory::getInstance()->createDispatcher();
|
||||
}
|
||||
else
|
||||
{
|
||||
pDispatcher_ = XFResourceFactory::getInstance()->getDefaultDispatcher();
|
||||
}
|
||||
|
||||
// Force hasOwnDispatcher attribute to false in case actual
|
||||
// dispatcher is the default dispatcher. This may happen
|
||||
// if in an IDF an other dispatcher is requested, but
|
||||
// only the default dispatcher is present.
|
||||
if (pDispatcher_ == XFResourceFactory::getInstance()->getDefaultDispatcher())
|
||||
{
|
||||
hasOwnDispatcher_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
XFBehavior::~XFBehavior()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void XFBehavior::startBehavior()
|
||||
{
|
||||
// Send initial event to state machine
|
||||
GEN(XFInitialEvent());
|
||||
|
||||
// Start dispatcher if behavior has its own dispatcher
|
||||
if (hasOwnDispatcher())
|
||||
{
|
||||
getDispatcher()->start();
|
||||
}
|
||||
}
|
||||
|
||||
void XFBehavior::pushEvent(XFEvent * pEvent, bool fromISR)
|
||||
{
|
||||
// Set owner
|
||||
pEvent->setBehavior(this);
|
||||
// Push to dispatchers event queue
|
||||
getDispatcher()->pushEvent(pEvent, fromISR);
|
||||
}
|
||||
|
||||
bool XFBehavior::deleteOnTerminate() const
|
||||
{
|
||||
return deleteOnTerminate_;
|
||||
}
|
||||
|
||||
void XFBehavior::setDeleteOnTerminate(bool deleteBehaviour)
|
||||
{
|
||||
deleteOnTerminate_ = deleteBehaviour;
|
||||
}
|
||||
|
||||
XFBehavior::TerminateBehavior XFBehavior::process(const XFEvent * pEvent)
|
||||
{
|
||||
XFEventStatus eventStatus;
|
||||
|
||||
setCurrentEvent(pEvent);
|
||||
|
||||
eventStatus = processEvent();
|
||||
|
||||
setCurrentEvent(nullptr);
|
||||
|
||||
return (eventStatus == XFEventStatus::Terminate);
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFBehavior::getDispatcher()
|
||||
{
|
||||
return pDispatcher_;
|
||||
}
|
||||
|
||||
void XFBehavior::setCurrentEvent(const XFEvent * pEvent)
|
||||
{
|
||||
pCurrentEvent_ = pEvent;
|
||||
}
|
||||
|
||||
const XFEvent * XFBehavior::getCurrentEvent() const
|
||||
{
|
||||
return pCurrentEvent_;
|
||||
}
|
||||
|
||||
const XFTimeout * XFBehavior::getCurrentTimeout()
|
||||
{
|
||||
assert(getCurrentEvent()->getEventType() == XFEvent::Timeout);
|
||||
|
||||
return static_cast<const XFTimeout *>(getCurrentEvent());
|
||||
}
|
8
src/xf/core/customevent.cpp
Normal file
8
src/xf/core/customevent.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "xf/customevent.h"
|
||||
|
||||
XFCustomEvent::XFCustomEvent(int id, interface::XFReactive * pBehavior)
|
||||
: XFEvent(XFEvent::Event, id, pBehavior),
|
||||
bDeleteAfterConsume_(true)
|
||||
{
|
||||
|
||||
}
|
11
src/xf/core/initialevent.cpp
Normal file
11
src/xf/core/initialevent.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "xf/initialevent.h"
|
||||
|
||||
XFInitialEvent::XFInitialEvent()
|
||||
: XFEvent(XFEvent::Initial, 0, nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool XFInitialEvent::deleteAfterConsume() const
|
||||
{
|
||||
return true;
|
||||
}
|
11
src/xf/core/nulltransition.cpp
Normal file
11
src/xf/core/nulltransition.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "xf/nulltransition.h"
|
||||
|
||||
XFNullTransition::XFNullTransition(interface::XFReactive * pBehavior)
|
||||
: XFEvent(XFEvent::NullTransition, 0, pBehavior)
|
||||
{
|
||||
}
|
||||
|
||||
bool XFNullTransition::deleteAfterConsume() const
|
||||
{
|
||||
return true;
|
||||
}
|
19
src/xf/core/timeout.cpp
Normal file
19
src/xf/core/timeout.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "xf/timeout.h"
|
||||
|
||||
XFTimeout::XFTimeout(int id, int interval, interface::XFReactive * pBehavior)
|
||||
: XFEvent(XFEvent::Timeout, id, pBehavior),
|
||||
interval_(interval),
|
||||
relTicks_(interval)
|
||||
{
|
||||
}
|
||||
|
||||
bool XFTimeout::operator ==(const XFTimeout & timeout) const
|
||||
{
|
||||
// Check behavior and timeout id attributes, if there are equal
|
||||
return (pBehavior_ == timeout.pBehavior_ && getId() == timeout.getId()) ? true : false;
|
||||
}
|
||||
|
||||
bool XFTimeout::deleteAfterConsume() const
|
||||
{
|
||||
return true;
|
||||
}
|
2515
src/xf/doxygen/Doxyfile
Normal file
2515
src/xf/doxygen/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
1556
src/xf/doxygen/xf.tag
Normal file
1556
src/xf/doxygen/xf.tag
Normal file
File diff suppressed because it is too large
Load Diff
101
src/xf/include/xf/behavior.h
Normal file
101
src/xf/include/xf/behavior.h
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef XF_BEHAVIOR_H
|
||||
#define XF_BEHAVIOR_H
|
||||
|
||||
#include "xf/interface/reactive.h"
|
||||
#include "xf/interface/dispatcher.h"
|
||||
#include "xf/eventstatus.h"
|
||||
#include "xf/initialevent.h"
|
||||
#include "xf/nulltransition.h"
|
||||
#include "xf/timeout.h"
|
||||
|
||||
class XFTimeout;
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Base class for state machines, activities, process and data flows.
|
||||
*
|
||||
* Reactive class implementing a behavior. This class can be used to
|
||||
* implement a state machine behavior or an activity behavior.
|
||||
*
|
||||
* Override the processEvent() operation in the inherited class to implement
|
||||
* your state machine behavior. The processEvent() method gets automatically
|
||||
* called every time an event or timeout arrives. The event (or timeout) can
|
||||
* be accessed via the getCurrentEvent() method.
|
||||
*/
|
||||
class XFBehavior : public interface::XFReactive
|
||||
{
|
||||
public:
|
||||
#define GEN(event) pushEvent(new event)
|
||||
|
||||
/**
|
||||
* @brief Default constructor for the behavior.
|
||||
*
|
||||
* Per default the XFBehavior chooses the 'default dispatcher' for event processing. In
|
||||
* case the ownDispatcher parameter is set to true, the XFBehavior creates internally
|
||||
* a separate dispatcher.
|
||||
*
|
||||
* @param ownDispatcher Set to true to get dedicated dispatcher for this behavior.
|
||||
*/
|
||||
explicit XFBehavior(bool ownDispatcher = false);
|
||||
~XFBehavior() override;
|
||||
|
||||
void startBehavior() override; ///< Starts the behavior, resp. the state machine.
|
||||
|
||||
void pushEvent(XFEvent * pEvent, bool fromISR=false) override;
|
||||
|
||||
bool deleteOnTerminate() const override;
|
||||
void setDeleteOnTerminate(bool deleteBehaviour) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Executes the current event in its implemented behavior.
|
||||
* This method needs to be overridden to implement the
|
||||
* behavior (i.e. state machine) needed.
|
||||
*/
|
||||
virtual XFEventStatus processEvent() = 0;
|
||||
|
||||
const XFEvent * getCurrentEvent() const; ///< Returns the current event to be processed in processEvent().
|
||||
interface::XFDispatcher * getDispatcher(); ///< Returns reference to #_pDispatcher.
|
||||
inline bool hasOwnDispatcher() const { return hasOwnDispatcher_; } ///< True if behavior has its own dispatcher.
|
||||
|
||||
|
||||
/** \brief Returns a reference to the actually processed timeout.
|
||||
*
|
||||
* Will work only if the current event is of type IXFEvent::Timeout.
|
||||
*/
|
||||
const XFTimeout * getCurrentTimeout();
|
||||
|
||||
inline void scheduleTimeout(int timeoutId, int interval) { getDispatcher()->scheduleTimeout(timeoutId, interval, this); } ///< @brief Schedules a timeout for this state machine.
|
||||
inline void unscheduleTimeout(int timeoutId) { getDispatcher()->unscheduleTimeout(timeoutId, this); } ///< @brief Unschedules a timeout for this state machine.
|
||||
|
||||
private:
|
||||
void setCurrentEvent(const XFEvent * pEvent); ///< Sets the current event to be processed in processEvent().
|
||||
|
||||
/**
|
||||
* \brief Processes the given event.
|
||||
*
|
||||
* The dispatcher calls this method every time a new event
|
||||
* or timeout arrives. The process method stores the actual
|
||||
* event using the #_pCurrentEvent and then calls
|
||||
* processEvent().
|
||||
*
|
||||
* In case you intend to call process() inside your state machine you
|
||||
* are doing something wrong! Call GEN() or pushEvent() instead!
|
||||
*
|
||||
* \param pEvent The event to process.
|
||||
*/
|
||||
TerminateBehavior process(const XFEvent * pEvent) override;
|
||||
|
||||
|
||||
protected:
|
||||
interface::XFDispatcher * pDispatcher_; ///< Reference to dispatcher processing this behavior.
|
||||
bool hasOwnDispatcher_; ///< True if behavior has its own dispatcher, False if the default dispatcher is used.
|
||||
bool deleteOnTerminate_; ///< Indicates if the behavior can be deleted after reception of a 'terminate event'.
|
||||
const XFEvent * pCurrentEvent_; ///< Reference to actually processed event.
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_BEHAVIOR_H
|
51
src/xf/include/xf/customevent.h
Normal file
51
src/xf/include/xf/customevent.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef XF_CUSTOMEVENT_H
|
||||
#define XF_CUSTOMEVENT_H
|
||||
|
||||
#include "xf/xf.h"
|
||||
#include "xf/event.h"
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Base class for project related events.
|
||||
*
|
||||
* It is possible to create custom events by deriving new classes/events from
|
||||
* this class.
|
||||
* All custom events have `#Event` as event type. In the state machine the event
|
||||
* can be uniquely identified with `getEventType() == Event` and the event id
|
||||
* `getId()` given to the object at construction time.
|
||||
*
|
||||
* It is up to the devoper to handle the different event ids.
|
||||
*/
|
||||
class XFCustomEvent : public XFEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor for the class
|
||||
*
|
||||
* @param id Event identifier to identify the custom event (in the context of the behavior).
|
||||
* @param pBehavior The behavior for which the event was constructed (will consume the event).
|
||||
**/
|
||||
XFCustomEvent(int id, interface::XFReactive * pBehavior = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Tells the XF if the event should be deleted after processing.
|
||||
* @return True if the event should be deleted.
|
||||
*/
|
||||
bool deleteAfterConsume() const override { return bDeleteAfterConsume_; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Setter for #_bDeleteAfterConsume attribute.
|
||||
* @param bDeleteAfterConsume Parameter to be assigned. Default: true.
|
||||
*/
|
||||
void setDeleteAfterConsume(bool bDeleteAfterConsume = true) { bDeleteAfterConsume_ = bDeleteAfterConsume; }
|
||||
|
||||
protected:
|
||||
bool bDeleteAfterConsume_; ///< True if the XF should delete event after consumption/dispatching.
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_CUSTOMEVENT_H
|
74
src/xf/include/xf/event.h
Normal file
74
src/xf/include/xf/event.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef XF_EVENT_H
|
||||
#define XF_EVENT_H
|
||||
|
||||
namespace interface {
|
||||
class XFReactive;
|
||||
}
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Base class for all types of events and timeouts.
|
||||
*
|
||||
* Requirements:
|
||||
* - Needs to hold a property which allows to distinguish between different
|
||||
* types of events (#_eventType).
|
||||
* - Use an enumeration to define the type for the event type property (#XFEventType).
|
||||
* - The event type property needs to be set at initialization time and cannot be
|
||||
* changed afterwards.
|
||||
*/
|
||||
class XFEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Defines the types of events
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
Unknown = 0, ///< Unknown state (not initialized).
|
||||
Initial = 1, ///< Initial pseudostate.
|
||||
NullTransition = 2, ///< Event generated by the state machine to define a null transition.
|
||||
Event = 3, ///< Custom event.
|
||||
Timeout = 4, ///< Defines a timeout event.
|
||||
Terminate = -1 ///< Defines a terminate state. Will end the state machine.
|
||||
} XFEventType;
|
||||
|
||||
public :
|
||||
/**
|
||||
* Default class constructor
|
||||
*/
|
||||
XFEvent(XFEventType eventType, int id, interface::XFReactive * pBehavior) : eventType_(eventType), id_(id), pBehavior_(pBehavior) {}
|
||||
virtual ~XFEvent() {} ///< Class destructor
|
||||
|
||||
/** \brief Returns the type of the event.
|
||||
*
|
||||
* Can be used to distinguish between an event or a timeout.
|
||||
*/
|
||||
inline XFEventType getEventType() const { return eventType_; }
|
||||
|
||||
/** \brief Returns pointer to behavioral class.
|
||||
*
|
||||
* Returns a pointer to the behavioral class processing the event (see #_pBehavior).
|
||||
*/
|
||||
inline interface::XFReactive * getBehavior() const { return pBehavior_; }
|
||||
|
||||
/** \brief Sets pointer to behavioral class (see #_pBehavior).
|
||||
* Sets the behavior in which the event should be executed.
|
||||
*/
|
||||
inline void setBehavior(interface::XFReactive * pBehavior) { pBehavior_ = pBehavior; }
|
||||
|
||||
inline int getId() const { return id_; } ///< Returns #_id identifying the event in the behaviors context.
|
||||
|
||||
virtual bool deleteAfterConsume() const { return false; } ///< Tells the dispatcher if the event must be deleted or not.
|
||||
|
||||
protected:
|
||||
const XFEventType eventType_; ///< Holds the type of the event.
|
||||
int id_; ///< Event id
|
||||
|
||||
interface::XFReactive * pBehavior_; ///< Pointer to behavioral class processing the event.
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_EVENT_H
|
75
src/xf/include/xf/eventstatus.h
Normal file
75
src/xf/include/xf/eventstatus.h
Normal file
@ -0,0 +1,75 @@
|
||||
#ifndef XF_EVENTSTATUS_H
|
||||
#define XF_EVENTSTATUS_H
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Event status returned after event processing.
|
||||
*
|
||||
* The XFEventStatus is used after consumption of an event. It gives an
|
||||
* information on how the event was consument and how the framework should
|
||||
* react.
|
||||
*/
|
||||
class XFEventStatus
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Status values about the event processed.
|
||||
*
|
||||
* \see XFBehavior::process
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
Unknown = 0,
|
||||
Consumed = 0x0001, ///< Event consumed
|
||||
NotConsumed = 0x0002, ///< Event not consumed
|
||||
RegionFinished = 0x0004, ///< Composite state machine finished
|
||||
Terminate = 0x0008 ///< Terminate state machine
|
||||
} eEventStatus;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param eventStatus Initial value of the event status.
|
||||
*/
|
||||
XFEventStatus(eEventStatus eventStatus = Unknown) : status_(eventStatus) {}
|
||||
|
||||
/**
|
||||
* Checks if both variables contain the same event status.
|
||||
*/
|
||||
bool operator == (const XFEventStatus::eEventStatus & eventStatus) const
|
||||
{
|
||||
return (this->status_ == eventStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief OR assignment.
|
||||
*
|
||||
* OR's the right event status with the left event status.
|
||||
*/
|
||||
void operator |= (const XFEventStatus & eventStatus)
|
||||
{
|
||||
unsigned int s1 = status_, s2 = eventStatus.status_;
|
||||
s1 |= s2;
|
||||
status_ = (eEventStatus)s1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the given event status (r-value) is present in the actual (l-value).
|
||||
*/
|
||||
bool is(const eEventStatus eventStatus) const
|
||||
{
|
||||
unsigned int mask = (unsigned int)eventStatus;
|
||||
return ((((unsigned int)status_) & mask) == mask);
|
||||
}
|
||||
|
||||
public:
|
||||
eEventStatus status_; ///< Attribute containing the status of the event.
|
||||
};
|
||||
|
||||
typedef XFEventStatus::eEventStatus eEventStatus;
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_EVENTSTATUS_H
|
25
src/xf/include/xf/initialevent.h
Normal file
25
src/xf/include/xf/initialevent.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef INITIALEVENT_H
|
||||
#define INITIALEVENT_H
|
||||
|
||||
#include "xf/event.h"
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initial event to start a behavior.
|
||||
*
|
||||
* Represents for example the first transition executed
|
||||
* in a state machine.
|
||||
*/
|
||||
class XFInitialEvent : public XFEvent
|
||||
{
|
||||
public:
|
||||
XFInitialEvent();
|
||||
|
||||
bool deleteAfterConsume() const override;
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // INITIALEVENT_H
|
98
src/xf/include/xf/interface/dispatcher.h
Normal file
98
src/xf/include/xf/interface/dispatcher.h
Normal file
@ -0,0 +1,98 @@
|
||||
#ifndef XF_INTERFACE_DISPATCHER_H
|
||||
#define XF_INTERFACE_DISPATCHER_H
|
||||
|
||||
#include "xf/event.h"
|
||||
|
||||
class XF;
|
||||
|
||||
namespace interface {
|
||||
|
||||
class XFReactive;
|
||||
class XFThread;
|
||||
|
||||
/**
|
||||
* @brief Interface for the XF dispatcher providing the event processing loop.
|
||||
*
|
||||
* Depending on the implementation the dispatcher is executed by
|
||||
* an internal thread. It is up to the port implementation how
|
||||
* the class behaves.
|
||||
*
|
||||
* The dispatcher should at least provide a queue to hold events
|
||||
* and an algorithm (typically in execute()) that dispatches the queued
|
||||
* events to the associated behavior (eq. state machine, activity).
|
||||
*
|
||||
* There may exist multiple dispatchers. Each behavior needs to be
|
||||
* bound to a dispatcher. One dispatcher may serve different behaviors.
|
||||
*
|
||||
* In an IDF the attribute _pThread is usually null.
|
||||
*/
|
||||
class XFDispatcher
|
||||
{
|
||||
friend class ::XF;
|
||||
|
||||
public:
|
||||
virtual ~XFDispatcher() = default;
|
||||
|
||||
virtual bool isActive() const = 0; ///< True if dispatcher has its own thread.
|
||||
|
||||
virtual void start() = 0; ///< Starts the thread.
|
||||
virtual void stop() = 0; ///< Stops the thread.
|
||||
virtual void pushEvent(XFEvent * pEvent, bool fromISR=false) = 0; ///< Adds event to the events queue.
|
||||
/**
|
||||
* @brief Adds a new timeout to be handled.
|
||||
*
|
||||
* The Thread will forward the timeout information to the timeout
|
||||
* manager which is responsible to handle all timeouts.
|
||||
*/
|
||||
virtual void scheduleTimeout(int timeoutId, int interval, interface::XFReactive * pReactive) = 0;
|
||||
|
||||
/**
|
||||
* @brief Removes all timeouts corresponding the given parameters.
|
||||
*/
|
||||
virtual void unscheduleTimeout(int timeoutId, interface::XFReactive * pReactive) = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructor is protected because only method createInstance()
|
||||
* should be called to create Dispatcher instances
|
||||
*/
|
||||
XFDispatcher() = default;
|
||||
|
||||
/**
|
||||
* @brief Returns pointer to thread executing the behavior.
|
||||
*
|
||||
* Within an IDF no threads are present and this method returns
|
||||
* always null.
|
||||
*/
|
||||
virtual interface::XFThread * getThread() const { return nullptr; }
|
||||
|
||||
/**
|
||||
* @brief Main loop of the dispatcher. Implements event loop processing.
|
||||
*/
|
||||
virtual int execute(const void * param = nullptr) = 0;
|
||||
|
||||
/**
|
||||
* @brief Executes once the dispatcher.
|
||||
*
|
||||
* Usually, this method must not be called explicitly. The
|
||||
* standard way to call the dispatcher is to call execute().
|
||||
*
|
||||
* This method can be called by the Thread (or main function) if it
|
||||
* must perform concurrent (non-XF related) tasks in addition.
|
||||
*
|
||||
* When using this method start() must not be called.
|
||||
*/
|
||||
virtual int executeOnce() = 0;
|
||||
|
||||
/**
|
||||
* @brief Dispatches the event to the corresponding behavioral part.
|
||||
*
|
||||
* For example the state machine which should process the event.
|
||||
*
|
||||
* \param pEvent The event to dispatch
|
||||
*/
|
||||
virtual void dispatchEvent(const XFEvent * pEvent) const = 0;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_DISPATCHER_H
|
27
src/xf/include/xf/interface/eventqueue.h
Normal file
27
src/xf/include/xf/interface/eventqueue.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef XF_INTERFACE_EVENT_QUEUE_H
|
||||
#define XF_INTERFACE_EVENT_QUEUE_H
|
||||
|
||||
class XFEvent;
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface to be implemented by the event queue
|
||||
*/
|
||||
class XFEventQueue
|
||||
{
|
||||
public:
|
||||
virtual ~XFEventQueue() = default;
|
||||
|
||||
virtual bool empty() const = 0; ///< Returns true if no event is in the queue.
|
||||
virtual bool push(const XFEvent * pEvent, bool fromISR = false) = 0; ///< Pushes the given event onto the queue.
|
||||
virtual const XFEvent * front() = 0; ///< Returns pointer to next event to pop.
|
||||
virtual void pop() = 0; ///< Pops the next event from the queue.
|
||||
virtual bool pend() = 0; ///< Wait for the next event to arrive. Returns true if an event is in the queue.
|
||||
|
||||
public:
|
||||
XFEventQueue() = default;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_EVENT_QUEUE_H
|
56
src/xf/include/xf/interface/mutex.h
Normal file
56
src/xf/include/xf/interface/mutex.h
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef XF_INTERFACE_MUTEX_H
|
||||
#define XF_INTERFACE_MUTEX_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Mutex interface needed by the XF to access a mutex.
|
||||
*
|
||||
* This interface only needs to be implemented for an XF port using
|
||||
* an underlying OS. An IDF based XF does not need to provide a
|
||||
* mutex.
|
||||
*
|
||||
* A non-recursive mutex needs to be implemented.
|
||||
*/
|
||||
class XFMutex
|
||||
{
|
||||
public:
|
||||
virtual ~XFMutex() = default;
|
||||
|
||||
virtual void lock() = 0; ///< Blocks until the mutex becomes available.
|
||||
virtual void unlock() = 0; ///< Releases the mutex so it can be taken by other threads.
|
||||
|
||||
/**
|
||||
* @brief Tries to get the mutex.
|
||||
*
|
||||
* If timeout is 0 method will leave immediately and then the return parameter indicates it the
|
||||
* mutex could be taken or not. Giving a negative value will block the thread until the mutex
|
||||
* becomes available.
|
||||
*/
|
||||
virtual bool tryLock(int32_t timeout = 0) = 0;
|
||||
|
||||
/**
|
||||
* @brief Creates and returns a new mutex instance.
|
||||
* @return Pointer to the created mutex object.
|
||||
*
|
||||
* The implementation of this method needs to be provided by
|
||||
* every XF port realizing a Mutex with this XFMutex interface.
|
||||
* Best way is to implement this method in the mutex.cpp
|
||||
* (or mutex-default.cpp) file of the XF port.
|
||||
*
|
||||
* Attention:
|
||||
* Do not forget to create an object of the class realizing
|
||||
* the interface and then return this object.
|
||||
*
|
||||
* You cannot instanciate an object of an abstract class!
|
||||
*/
|
||||
static XFMutex * create();
|
||||
|
||||
protected:
|
||||
XFMutex() = default;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_MUTEX_H
|
53
src/xf/include/xf/interface/reactive.h
Normal file
53
src/xf/include/xf/interface/reactive.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef XF_INTERFACE_REACTIVE_H
|
||||
#define XF_INTERFACE_REACTIVE_H
|
||||
|
||||
#include <string>
|
||||
#include "xf/event.h"
|
||||
#include "xf/eventstatus.h"
|
||||
|
||||
class XFDispatcherDefault;
|
||||
class XFDispatcherActiveDefault;
|
||||
class XFDispatcherPort;
|
||||
class XFDispatcherActivePort;
|
||||
class XFDispatcher;
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface to receive and process events.
|
||||
*
|
||||
* Interface that needs to be implemented by every class having a
|
||||
* behavior. Interface methods are needed by the other parts of the XF.
|
||||
*
|
||||
* This interface is used by the dispatcher to process events.
|
||||
*/
|
||||
class XFReactive
|
||||
{
|
||||
// Only XFDispatchers should get access to the 'process' method
|
||||
friend class ::XFDispatcherDefault;
|
||||
friend class ::XFDispatcherActiveDefault;
|
||||
friend class ::XFDispatcherPort;
|
||||
friend class ::XFDispatcherActivePort;
|
||||
friend class ::XFDispatcher;
|
||||
|
||||
public:
|
||||
using TerminateBehavior = bool;
|
||||
|
||||
public:
|
||||
virtual ~XFReactive() = default;
|
||||
|
||||
virtual void startBehavior() = 0; ///< Starts the behavior.
|
||||
virtual void pushEvent(XFEvent * pEvent, bool fromISR = false) = 0; ///< Injects an event into the class.
|
||||
|
||||
virtual bool deleteOnTerminate() const = 0; ///< Tells XF to delete behavior when receiving terminate event.
|
||||
virtual void setDeleteOnTerminate(bool deleteBehaviour) = 0; ///< Sets/Clears the 'delete on terminate' property.
|
||||
|
||||
protected:
|
||||
virtual TerminateBehavior process(const XFEvent * pEvent) = 0; ///< Called by the dispatcher to process an event.
|
||||
|
||||
protected:
|
||||
XFReactive() = default;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_REACTIVE_H
|
76
src/xf/include/xf/interface/resourcefactory.h
Normal file
76
src/xf/include/xf/interface/resourcefactory.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef XF_INTERFACE_RESOURCE_FACTORY_H
|
||||
#define XF_INTERFACE_RESOURCE_FACTORY_H
|
||||
|
||||
#include "xf/interface/dispatcher.h"
|
||||
#include "xf/interface/thread.h"
|
||||
#include "xf/interface/mutex.h"
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Responsible to create and return XF resources.
|
||||
*
|
||||
* The XF resource factory provides instances of following classes
|
||||
* - Dispatcher
|
||||
* - Thread
|
||||
* - Mutex
|
||||
*
|
||||
* The XFResourceFactory::getInstance() method needs to be implemented
|
||||
* in the class realizing this interface.
|
||||
*
|
||||
*/
|
||||
class XFResourceFactory
|
||||
{
|
||||
public:
|
||||
static XFResourceFactory * getInstance(); ///< Returns a pointer to the unique instance of the XF resource factory.
|
||||
|
||||
/**
|
||||
* @brief Returns the default dispatcher.
|
||||
*
|
||||
* In case a bahavior does not have a specific dispatcher the
|
||||
* default dispatcher ist used.
|
||||
*
|
||||
* @return A pointer to the default dispatcher.
|
||||
*/
|
||||
virtual interface::XFDispatcher * getDefaultDispatcher() = 0;
|
||||
|
||||
/**
|
||||
* @brief Creates a new dispatcher.
|
||||
*
|
||||
* Per default this method returns a new active dispatcher. In
|
||||
* case there is no OS present (IDF) the default dispatcher may
|
||||
* be returned.
|
||||
*
|
||||
* @return The new dispatcher
|
||||
*/
|
||||
virtual interface::XFDispatcher * createDispatcher() = 0;
|
||||
|
||||
/**
|
||||
* @brief Creates a new Thread.
|
||||
* @param pProvider The instance providing the entry method.
|
||||
* @param entryMethod The method to by called by the new thread.
|
||||
* @param threadName The name of the thread.
|
||||
* @param stackSize The stack size of the thread.
|
||||
* @return Pointer to new thread
|
||||
*
|
||||
* The method may return null in case there is no OS present.
|
||||
*/
|
||||
virtual interface::XFThread * createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize = 0) = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns a new mutex.
|
||||
* @return Pointer to new mutex.
|
||||
*/
|
||||
virtual interface::XFMutex * createMutex() = 0;
|
||||
|
||||
virtual ~XFResourceFactory() = default;
|
||||
|
||||
protected:
|
||||
XFResourceFactory() = default;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_RESOURCE_FACTORY_H
|
60
src/xf/include/xf/interface/thread.h
Normal file
60
src/xf/include/xf/interface/thread.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef XF_INTERFACE_THREAD_H
|
||||
#define XF_INTERFACE_THREAD_H
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
XF_THREAD_PRIO_UNKNOWN = 0,
|
||||
XF_THREAD_PRIO_LOW = 5,
|
||||
XF_THREAD_PRIO_NORMAL = 10,
|
||||
XF_THREAD_PRIO_HIGH = 15,
|
||||
XF_THREAD_PRIO_MAX = 20
|
||||
} XFThreadPriority;
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface to be implemented by the class providing the thread entry method.
|
||||
*/
|
||||
class XFThreadEntryPointProvider
|
||||
{
|
||||
public:
|
||||
virtual ~XFThreadEntryPointProvider() = default;
|
||||
protected:
|
||||
XFThreadEntryPointProvider() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface for a Thread.
|
||||
*
|
||||
* Thread interface representing the instance executing the behavior. In an OS less XF
|
||||
* (hence an IDF), usually this class is not needed. In an XF interfacing an OS,
|
||||
* multiple instances can be made, each interfacing the real OS thread.
|
||||
*
|
||||
* Thread instances can be created using the ResourceFactory instance.
|
||||
*
|
||||
* The XF assumes that the Thread is in suspend state after creation. Automatically
|
||||
* starting the thread after creation may lead to unwanted behavior!
|
||||
*/
|
||||
class XFThread
|
||||
{
|
||||
public:
|
||||
virtual ~XFThread() = default;
|
||||
|
||||
typedef void (XFThreadEntryPointProvider::*EntryMethodBody)(const void *); ///< Prototype of method to be executed by the thread.
|
||||
|
||||
virtual void start() = 0; ///< Starts the thread.
|
||||
virtual void stop() = 0; ///< Requests the thread to stop execution.
|
||||
|
||||
virtual void setPriority(XFThreadPriority priority) = 0; ///< Set the thread priority.
|
||||
virtual XFThreadPriority getPriority() const = 0; ///< Returns the thread priority.
|
||||
|
||||
virtual void delay(uint32_t milliseconds) = 0; ///< Causes the thread to sleep (for the given milliseconds).
|
||||
|
||||
protected:
|
||||
XFThread() = default;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_THREAD_H
|
89
src/xf/include/xf/interface/timeoutmanager.h
Normal file
89
src/xf/include/xf/interface/timeoutmanager.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef XF_INTERFACE_TIMEOUTMANAGER_H
|
||||
#define XF_INTERFACE_TIMEOUTMANAGER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace interface {
|
||||
class XFReactive;
|
||||
}
|
||||
class XFTimeout;
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface for TimerManager classes (and some few 'tick' stuff already provided).
|
||||
*
|
||||
* The TimeoutManager is responsible to handle timeouts used
|
||||
* in state machines. It decrements them accordingly and inject
|
||||
* them back to the state machine when timeouted.
|
||||
*
|
||||
* <b>Requirements:</b>
|
||||
* - Implements the Singleton pattern
|
||||
* - Handle timeouts (hold, decrement, re-inject)
|
||||
*/
|
||||
class XFTimeoutManager
|
||||
{
|
||||
public:
|
||||
virtual ~XFTimeoutManager() = default;
|
||||
|
||||
static XFTimeoutManager * getInstance(); ///< Returns a pointer to the single instance of TimeoutManager.
|
||||
|
||||
/**
|
||||
* Sets the time interval in milliseconds in which the timeout manager
|
||||
* should handle the timeouts.
|
||||
*/
|
||||
virtual void initialize(int32_t tickInterval)
|
||||
{
|
||||
tickInterval_ = tickInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns tick interval in milliseconds.
|
||||
*/
|
||||
virtual int32_t getTickInterval() const
|
||||
{
|
||||
return tickInterval_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the timeout manager.
|
||||
*/
|
||||
virtual void start() = 0;
|
||||
|
||||
/**
|
||||
* Adds a timeout to the timeout manager.
|
||||
*
|
||||
* \param timeoutId The timeout id known by the reactive parameter. Is needed by the reactive part to uniquely identify the timeout.
|
||||
* \param interval The time in milliseconds to wait until the timeout expires.
|
||||
* \param pReactive The reactive instance where to inject the timeout when it timeouts.
|
||||
*/
|
||||
virtual void scheduleTimeout(int32_t timeoutId, int32_t interval, interface::XFReactive * pReactive) = 0;
|
||||
|
||||
/**
|
||||
* Removes all timeouts corresponding the given parameters.
|
||||
*/
|
||||
virtual void unscheduleTimeout(int32_t timeoutId, interface::XFReactive * pReactive) = 0;
|
||||
|
||||
/** \brief Called periodically with a delay defined by TimeoutManager::_tickInterval.
|
||||
*
|
||||
* On each call to this method, TimeoutManager::_tickInterval will be removed from the
|
||||
* timeouts.
|
||||
* When a timeout expires it is pushed back to the dispatcher. To which
|
||||
* dispatcher it must be given is known by the reactive instance to which the timeout
|
||||
* belongs.
|
||||
*/
|
||||
virtual void tick() = 0;
|
||||
|
||||
protected:
|
||||
XFTimeoutManager() :
|
||||
tickInterval_(0)
|
||||
{}
|
||||
|
||||
virtual void addTimeout(XFTimeout * pNewTimeout) = 0; ///< Adds the timeout to the list of timeouts.
|
||||
|
||||
protected:
|
||||
int32_t tickInterval_; ///< Interval in milliseconds the TimeoutManager is decrementing the timeouts.
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_TIMEOUTMANAGER_H
|
33
src/xf/include/xf/nulltransition.h
Normal file
33
src/xf/include/xf/nulltransition.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef XF_NULLTRANSITION_H
|
||||
#define XF_NULLTRANSITION_H
|
||||
|
||||
#include "xf.h"
|
||||
#include "xf/event.h"
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief State machine transition without trigger.
|
||||
*
|
||||
* Represents a transition in a state machine having no trigger.
|
||||
*
|
||||
* In case one wants to directly transition from one state to
|
||||
* an other (without a trigger) a null transition must be pushed.
|
||||
*/
|
||||
class XFNullTransition : public XFEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param pBehavior Behavior in which the null transition will be executed.
|
||||
*/
|
||||
XFNullTransition(interface::XFReactive * pBehavior = nullptr);
|
||||
|
||||
bool deleteAfterConsume() const override;
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_NULLTRANSITION_H
|
59
src/xf/include/xf/timeout.h
Normal file
59
src/xf/include/xf/timeout.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef XF_TIMEOUT_H
|
||||
#define XF_TIMEOUT_H
|
||||
|
||||
#include "xf/event.h"
|
||||
|
||||
namespace interface {
|
||||
class XFTimeoutManager;
|
||||
}
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Used by the TimeoutManager to create and handle a timeout.
|
||||
*
|
||||
* Timeouts are created automatically by the TimeoutManager when
|
||||
* scheduling a timeout. After expiration they are queued to the event queue
|
||||
* and afterwards dispatched to the corresonding behavior.
|
||||
*
|
||||
* A timeout can be identified by checking against #Timeout using
|
||||
* the `getEventType()` method.
|
||||
*
|
||||
* XFTimeout is inheriting from XFEvent, so every timeout is
|
||||
* also an event.
|
||||
*/
|
||||
class XFTimeout : public XFEvent
|
||||
{
|
||||
friend class interface::XFTimeoutManager;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor of the class.
|
||||
* \param id The id given by the behavioral class to uniquely identifying the timeout
|
||||
* \param interval The interval in milliseconds the timeout expires
|
||||
* \param pBehavior Pointer to behavioral class to which the timeout belongs
|
||||
*/
|
||||
XFTimeout(int id, int interval, interface::XFReactive * pBehavior);
|
||||
|
||||
/**
|
||||
* Operator checks if #_pBehavior and #_id are equal and returns
|
||||
* true if so. All other attributes get no attention.
|
||||
*/
|
||||
bool operator ==(const XFTimeout & timeout) const;
|
||||
|
||||
bool deleteAfterConsume() const override; ///< Tells the dispatcher if the event must be deleted or not.
|
||||
|
||||
inline void setRelTicks(int relTicks) { relTicks_ = relTicks; } ///< Sets remaining ticks.
|
||||
inline int getRelTicks() const { return relTicks_; } ///< Returns remaining ticks.
|
||||
inline void substractFromRelTicks(int ticksToSubstract) { relTicks_ -= ticksToSubstract; } ///< Substracts `ticksToSubstract` from remaining ticks.
|
||||
inline void addToRelTicks(int ticksToAdd) { relTicks_ += ticksToAdd; } ///< Adds `ticksToAdd` to remaining ticks.
|
||||
|
||||
protected:
|
||||
int interval_; ///< Timeout interval
|
||||
int relTicks_; ///< Used by the TimeoutManager to calculate remaining time. Can get negative!
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_TIMEOUT_H
|
6
src/xf/include/xf/xf-core.dox
Normal file
6
src/xf/include/xf/xf-core.dox
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
/** @defgroup xf_core XF Core Classes
|
||||
*
|
||||
* XF core classes.
|
||||
*
|
||||
*/
|
171
src/xf/include/xf/xf.h
Normal file
171
src/xf/include/xf/xf.h
Normal file
@ -0,0 +1,171 @@
|
||||
#ifndef XF_XF_H
|
||||
#define XF_XF_H
|
||||
|
||||
#include "config/xf-config.h"
|
||||
|
||||
//
|
||||
// What is seen only by the C++ compiler
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "xf/interface/dispatcher.h"
|
||||
|
||||
/** \mainpage PTR Execution Framework Documentation
|
||||
*
|
||||
* \section sec_xf_intro Introduction
|
||||
*
|
||||
* This library implements an e<b>X</b>ecution <b>F</b>ramework (XF) to drive finite
|
||||
* state machines. Using this framework, it is possible to drive multiple state machines
|
||||
* in a concurrent manner (pseudo-parallel) without having an operating system.
|
||||
*
|
||||
* The XF defines an interface which gives the ability to reimplement parts of the XF to
|
||||
* make changes to an other target/platform. It is also possible to let the XF run with an RTOS.
|
||||
* This gives the possibility to run state machines in a OS like concurrent manner with
|
||||
* threads provided by the underlying RTOS.
|
||||
*
|
||||
* \section sec_xf_comp XF Component Diagram
|
||||
* The XF is split into two parts. One part is the XF core containing classes which
|
||||
* never change across platforms. The other part is the XF port containing classes
|
||||
* adjusted for a specific platform:
|
||||
*
|
||||
* \image html comp-xf.png "Component Class Diagram"
|
||||
*
|
||||
* The XF core together with a port forms a complete XF which can be integrated into
|
||||
* a software project.
|
||||
*
|
||||
* \section sec_xf_cmd XF Class Diagram
|
||||
*
|
||||
* Following class diagram shows the basic relations between the most important classes
|
||||
* in the PTR XF. It shall give you a basic understanding about the relations between
|
||||
* these classes:
|
||||
*
|
||||
* \image html cmd-xf.png "XF Class Diagram"
|
||||
*
|
||||
* \section sec_xf_start Starting Point
|
||||
*
|
||||
* A good point to jump into the definitions of the classes is the `#XF` class. Other classes
|
||||
* of interest are `interface::XFTimeoutManager`, `interface::XFDispatcher` and `interface::XFReactive`.
|
||||
*
|
||||
* \section sec_xf_external_links Links to related Documentation
|
||||
* \if DOC_WITH_TESTBENCH
|
||||
* - <a href="../../../../../test-bench/doxygen/output/html/index.html">Test Bench Documentation</a>
|
||||
* \endif
|
||||
* - <a href="../../../../../src/mdw/trace/doxygen/output/html/index.html">Trace Documentation</a>
|
||||
*
|
||||
* \if DOC_WITH_RELEASE_HISTORY
|
||||
* \section sec_xf_releases XF Releases
|
||||
* \subsection xf_v_4_0_1 XF Version: 4.0.1 (2021-08)
|
||||
* - crc: Added parameter 'fromISR' for push() methods
|
||||
* - sth: Added XF_isRunning() function to port-functions.h
|
||||
* \subsection xf_v_4_0_0 XF Version: 4.0.0 (2021-05)
|
||||
* - crc: Migration from IDE-STM / CubeMX to CubeIDE
|
||||
* - crc: Changed CMSIS port from `CMSIS_RTOS_V1` to `CMSIS_RTOS_V2`
|
||||
* \subsection xf_v_3_3_2 XF Version: 3.3.2 (2020-09)
|
||||
* - sth: Added 'override' keywords to derived methods
|
||||
* - sth: Removed attribute '_mainDispatcher' from XFResourceFactoryDefault
|
||||
* \subsection xf_v_3_3_1 XF Version: 3.3.1 (2020-04)
|
||||
* - sth: Added XF::isRunning() method
|
||||
* \subsection xf_v_3_3_0 XF Version: 3.3.0 (2020-02)
|
||||
* - sth: Introduced per platform default port implementations (port/default-qt, port/default-idf, etc.)
|
||||
* - sth: Moved mutex and thread classes into the platform default port folders
|
||||
* - sth: Added 'interface::XFReactive::deleteOnTerminate()' method
|
||||
* \subsection xf_v_3_2_1 XF Version: 3.2.1 (2019-04)
|
||||
* - sth: Made several bugfixes.
|
||||
* \subsection xf_v_3_2 XF Version: 3.2 (2018-09)
|
||||
* - sth: Updated XF interfaces.
|
||||
* - sth: Added IDF_STM32CUBE, STM32CUBE_CMSIS_FREERTOS and ACTIVE_QT ports.
|
||||
* - sth: Removed old ports IDF_STM32F4 and CMSIS_RTOS_FREERTOS.
|
||||
* \subsection xf_v_3_1 XF Version: 3.1 (2017-11)
|
||||
* - sth: Fixed bug in removeTimeouts() method of XFTimeoutManager. Thanks to Gregory Dumoulin.
|
||||
* \subsection xf_v_3_0 XF Version: 3.0 (2017-10)
|
||||
* - sth: The new XF is providing interfaces to support other OS's.
|
||||
* - sth: Changed XF interfaces. Porting older applications to new XF need some adjustments.
|
||||
* - sth: Added 'port' folder to allow extensions to other platforms.
|
||||
* - sth: Added IDF_STM32F4, CMSIS_RTOS_FREERTOS and IDF_QT ports.
|
||||
* \subsection xf_v_2_1 XF Version: 2.1 (2015-03-02)
|
||||
* - sth: XFTimoutManager now returns timeouts with same value correctly.
|
||||
* \subsection xf_v_2_0 XF Version: 2.0 (2014-04-28)
|
||||
* - sth: Changed way how XFTimeoutManager handles timeouts which timeout at the same time.
|
||||
* Now new timeouts get behind the timeouts with the same (timeout) time.
|
||||
* \subsection xf_v_1_0 XF Version: 1.0 (2014-04-24)
|
||||
* - sth: Renamed class XFEvent to XFCustomEvent
|
||||
* - sth: Renamed IXFEvent to XFEvent (because it was never a real interface)
|
||||
* \subsection xf_v_0_5 XF Version: 0.5 (2013-12-09)
|
||||
* - sth: Now properly stopping and terminating MainThreadExec instance
|
||||
* - sth: Added new literal to XFEventStatus to handle composite states
|
||||
* \subsection xf_v_0_4 XF Version: 0.4 (2013-12-05)
|
||||
* - sth: Added scheduleTimeout and unscheduleTimeout to XFBehavior class (helper operations)
|
||||
* \subsection xf_v_0_3 XF Version: 0.3 (2013-09-19)
|
||||
* - sth: Added handling for static events (IXFEvent::deleteAfterConsume())
|
||||
* \subsection xf_v_0_2 XF Version: 0.2 (2011-08-14)
|
||||
* - sth: Fixed bug in XFTimeoutManager::addTimeout method
|
||||
* \subsection xf_v_0_1 XF Version: 0.1 (2010-11-26)
|
||||
* - sth: First release
|
||||
* \endif
|
||||
*/
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Static class grouping the basic methods for the XF together.
|
||||
*/
|
||||
class XF
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes the e<b>X</b>ecution <b>F</b>ramework (XF). Call
|
||||
* this method prior to initialize the other objects of the system.
|
||||
*
|
||||
* @param timeInterval The interval in milliseconds with which the TimeoutManager should run.
|
||||
* @param argc Optional parameter to pass application argument number to XF.
|
||||
* @param argv Optional parameter to pass application arguments to XF.
|
||||
*/
|
||||
static void initialize(int timeInterval = 10, int argc = 0, char * argv[] = nullptr);
|
||||
|
||||
/**
|
||||
* Starts execution of the framework. This
|
||||
* results in processing the events in main loop.
|
||||
*
|
||||
* This method is blocking.
|
||||
*/
|
||||
static int exec();
|
||||
|
||||
/**
|
||||
* Executes once the dispatcher. To be called regularly in a while loop.
|
||||
*
|
||||
* This method is non-blocking.
|
||||
*/
|
||||
static int execOnce();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns true in case the XF is initialized and running.
|
||||
*/
|
||||
static bool isRunning();
|
||||
|
||||
protected:
|
||||
static bool isInitialized_; ///< Changes from false to true after calling method initialize(int). Used to handle multiple calls to init(int).
|
||||
static bool isRunning_; ///< Tells if the XF is initialized and running.
|
||||
};
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
//
|
||||
// What is seen by the C and C++ compiler
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
void XF_initialize(int timeInterval); ///< Initializes XF within C code
|
||||
void XF_exec(); ///< Calls XF execution in C code (blocking call)
|
||||
void XF_execOnce(); ///< Calls XF execution in C code (non-blocking call)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_XF_H
|
62
src/xf/port/README.md
Normal file
62
src/xf/port/README.md
Normal file
@ -0,0 +1,62 @@
|
||||
# XF Ports
|
||||
|
||||
## Introduction
|
||||
An XF (execution framework) consist of a view classes which some need to be adjusted
|
||||
when used on another platform.
|
||||
|
||||
Following you will find a list of classes which may be adjusted/reimplemented when
|
||||
changing to another platform/environment:
|
||||
- `XF`
|
||||
- `ResourceFactory`
|
||||
- `TimeoutManager`
|
||||
- `Dispatcher`
|
||||
- `EventQueue`
|
||||
- `Thread`
|
||||
- `Mutex`
|
||||
|
||||
These classes are also named `port classes` because they can be ported to another
|
||||
platform. All port classes can be found in the _port_ folder whereas every port is
|
||||
located in a separate folder.
|
||||
|
||||
Every port may pick some default implementation classes from the _default_ folders
|
||||
also located in the _port_ folder.
|
||||
|
||||
In case you are going to implement an OS-less XF (hence an IDF) usually, you do not
|
||||
need to implement the classes `Thread` and `Mutex`.
|
||||
|
||||
## Default Port Classes
|
||||
There are already some default port class implementations present. You can find
|
||||
them in the `default` folder and may suit your needs for a first version
|
||||
of your XF. These default port classes are platform independent and can be
|
||||
used by any port implementation.
|
||||
|
||||
## Default Platform Classes
|
||||
Some classes depent on external resources like for example an OS. These
|
||||
classes are located in the _default-<platform>_ specific folders. Currently,
|
||||
the following default platfroms are available:
|
||||
|
||||
| Platform | Folder | Description |
|
||||
|--|--|--|
|
||||
| CMSIS-OS | [default-cmsis-os](./default-cmsis-os) | CMSIS-OS abstraction layer |
|
||||
| IDF | [default-idf](./default-idf) | Interrupt driven framework |
|
||||
| QT | [default-qt](./default-qt) | Qt library |
|
||||
|
||||
## Port Folder Structure
|
||||
In case you want to add support for another platform to the XF, you need to add a
|
||||
subfolder to the _port_ folder and put the port class files in there. Best is to
|
||||
take an already present port which is most similar to what you need, rename it and
|
||||
start adaption of these files.
|
||||
|
||||
You may also mix-up you port with classes from the _default_, _default-<platform>_
|
||||
folder and your custom folder (or even reference classes from other ports).
|
||||
|
||||
## Available Ports
|
||||
|
||||
Here is a list of currently available ports:
|
||||
|
||||
| Port Name | OS | Platform | Folder Name | Description |
|
||||
|--|--|--|--|--|
|
||||
| PORT_IDF_QT | Qt (IDF) | Qt library based implementation | idf-qt | XF support for OS X, Linux and Windows |
|
||||
| PORT_IDF_STM32CUBE | Bare-Metal (IDF) | STM32CubeMX based port | idf-stm32cube | XF for ARM Cortex based microcontrollers from STMicroelectronics |
|
||||
| PORT_STM32CUBE_CMSIS_FREERTOS | CMSIS OS (FreeRTOS) | Any platform supporting CMSIS OS | stm32cube-cmsis-freertos | FreeRTOS based port |
|
||||
| PORT_ACTIVE_QT | Qt multi-thread | Qt library based implementation | active-qt | XF support for OS X, Linux and Windows (multi-thread) |
|
38
src/xf/port/active-qt/README.md
Normal file
38
src/xf/port/active-qt/README.md
Normal file
@ -0,0 +1,38 @@
|
||||
# XF Port - Active Qt
|
||||
|
||||
This port folder contains specific classes for the _Active Qt_
|
||||
XF port.
|
||||
|
||||
# Classes used by the _Active Qt_ Port
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
|--|--|--|
|
||||
| XFTimeoutManagerDefault | xf/port/default/timeoutmanager-default.cpp | USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION |
|
||||
| XFDispatcherActiveDefault | xf/port/default/dispatcher-active.cpp | USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION |
|
||||
| XF | xf/port/idf-qt/xf.cpp | USE_XF_PORT_IDF_QT_XF_IMPLEMENTATION |
|
||||
| XFMutexPort | xf/port/default-qt/mutex-default.cpp | USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XFThreadPort | xf/port/default-qt/thread-default.cpp | USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XFEventQueuePort | xf/port/idf-qt/eventqueue.cpp | USE_XF_PORT_IDF_QT_EVENT_QUEUE_IMPLEMENTATION |
|
||||
| Port Functions | xf/port/idf-qt/port-functions.cpp | USE_XF_PORT_IDF_QT_PORT_FUNCTIONS_IMPLEMENTATION |
|
||||
| XFResourceFactoryPort | xf/port/active-qt/resourcefactory.cpp | USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION |
|
||||
|
||||
# Example _config/xf-config.h_ File
|
||||
```c++
|
||||
// Take all the port classes from the IDF_QT port expect...
|
||||
#define USE_XF_PORT_IDF_QT_XF_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_IDF_QT_EVENT_QUEUE_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_IDF_QT_PORT_FUNCTIONS_IMPLEMENTATION 1
|
||||
|
||||
// ... the resource factory. Must provide active dispatchers!
|
||||
#define USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION 1
|
||||
|
||||
// ... mutexes and threads from the 'default-qt' port package
|
||||
#define USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION 1
|
||||
|
||||
// ... and the remaining classes from the default port package.
|
||||
#define USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION 1
|
||||
|
||||
#include "idf-qt/eventqueue.h"
|
||||
```
|
BIN
src/xf/port/active-qt/README.pdf
Normal file
BIN
src/xf/port/active-qt/README.pdf
Normal file
Binary file not shown.
51
src/xf/port/active-qt/resourcefactory.cpp
Normal file
51
src/xf/port/active-qt/resourcefactory.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION != 0)
|
||||
|
||||
#include <QtGlobal>
|
||||
#include "xf/interface/mutex.h"
|
||||
#include "thread-default.h"
|
||||
#include "default/dispatcher-active.h"
|
||||
#include "resourcefactory.h"
|
||||
|
||||
using interface::XFMutex;
|
||||
|
||||
//static
|
||||
interface::XFResourceFactory * interface::XFResourceFactory::getInstance()
|
||||
{
|
||||
return XFResourceFactoryPort::getInstance();
|
||||
}
|
||||
|
||||
// static
|
||||
interface::XFResourceFactory * XFResourceFactoryPort::getInstance()
|
||||
{
|
||||
static XFResourceFactoryPort theResourceFactory;
|
||||
return &theResourceFactory;
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFResourceFactoryPort::getDefaultDispatcher()
|
||||
{
|
||||
static XFDispatcherActiveDefault mainDispatcher;
|
||||
return &mainDispatcher;
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFResourceFactoryPort::createDispatcher()
|
||||
{
|
||||
// Create the new active dispatcher
|
||||
return new XFDispatcherActiveDefault;
|
||||
}
|
||||
|
||||
interface::XFThread * XFResourceFactoryPort::createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize /* = 0 */)
|
||||
{
|
||||
return new XFThreadDefault(pProvider, entryMethod, threadName, stackSize);
|
||||
}
|
||||
|
||||
interface::XFMutex * XFResourceFactoryPort::createMutex()
|
||||
{
|
||||
return XFMutex::create();
|
||||
}
|
||||
|
||||
#endif // USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION
|
31
src/xf/port/active-qt/resourcefactory.h
Normal file
31
src/xf/port/active-qt/resourcefactory.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_H
|
||||
#define XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_H
|
||||
|
||||
#include "config/xf-config.h"
|
||||
|
||||
#if (USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION != 0)
|
||||
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "xf/interface/dispatcher.h"
|
||||
|
||||
class XFResourceFactoryPort : public interface::XFResourceFactory
|
||||
{
|
||||
public:
|
||||
~XFResourceFactoryPort() override {}
|
||||
|
||||
static interface::XFResourceFactory * getInstance();
|
||||
|
||||
interface::XFDispatcher * getDefaultDispatcher() override;
|
||||
interface::XFDispatcher * createDispatcher() override;
|
||||
interface::XFThread * createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize = 0) override;
|
||||
interface::XFMutex * createMutex() override;
|
||||
|
||||
protected:
|
||||
XFResourceFactoryPort() {}
|
||||
};
|
||||
|
||||
#endif // USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION
|
||||
#endif // XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_H
|
8
src/xf/port/active-qt/xf-port-active.pri
Normal file
8
src/xf/port/active-qt/xf-port-active.pri
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
INCLUDEPATH += $$PWD/..
|
||||
|
||||
SOURCES += \
|
||||
"$$PWD/resourcefactory.cpp"
|
||||
|
||||
HEADERS += \
|
||||
"$$PWD/resourcefactory.h"
|
24
src/xf/port/active-qt/xf-port-default.pri
Normal file
24
src/xf/port/active-qt/xf-port-default.pri
Normal file
@ -0,0 +1,24 @@
|
||||
#
|
||||
# This PRI file takes only the classes needed from the
|
||||
# 'default' port.
|
||||
#
|
||||
|
||||
INCLUDEPATH += $$PWD/..
|
||||
|
||||
# Path to default implementation of the XF port
|
||||
DEFAULT_IMPL_PATH = $$PWD/../default
|
||||
|
||||
DEFAULT_IMPL_SOURCES += \
|
||||
"$${DEFAULT_IMPL_PATH}/xf-default.cpp" \
|
||||
"$${DEFAULT_IMPL_PATH}/timeoutmanager-default.cpp" \
|
||||
"$${DEFAULT_IMPL_PATH}/dispatcher-active.cpp"
|
||||
|
||||
DEFAULT_IMPL_HEADERS += \
|
||||
"$${DEFAULT_IMPL_PATH}/timeoutmanager-default.h" \
|
||||
"$${DEFAULT_IMPL_PATH}/dispatcher-active.h"
|
||||
|
||||
SOURCES += \
|
||||
$${DEFAULT_IMPL_SOURCES}$$
|
||||
|
||||
HEADERS += \
|
||||
$${DEFAULT_IMPL_HEADERS}$$
|
39
src/xf/port/default-cmsis-os/README.md
Normal file
39
src/xf/port/default-cmsis-os/README.md
Normal file
@ -0,0 +1,39 @@
|
||||
# CMSIS-OS Platform Default Port
|
||||
|
||||
This folder provides a default implementation for CMSIS-OS platform
|
||||
related XF classes. You can use these classes to construct a CMSIS-OS
|
||||
based XF.
|
||||
|
||||
If these classes do not suit your needs, they can be reimplemented for
|
||||
your platform. Create an additional folder in the 'port' folder and
|
||||
implement there the classes you need for your platform.
|
||||
|
||||
# Available Default CMSIS-OS Port Classes
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
| -------------- | ------------------------------------- | --------------------------------------- |
|
||||
| XFMutexDefault | xf/port/default-cmsis-os/mutex-default.cpp | USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION |
|
||||
| XFThreadDefault | xf/port/default-cmsis-os/thread-default.cpp | USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION |
|
||||
|
||||
If you need more information about the classes mentioned above, please
|
||||
have a look into their header files and the doxygen comments in code.
|
||||
|
||||
# Example _config/xf-config.h_ File
|
||||
|
||||
Following you will find an example giving you a basic idea which define
|
||||
to set in the application specific _config/xf-config.h_ file.
|
||||
|
||||
The _Stm32Cube CMSIS FreeRTOS_ port uses these classes:
|
||||
|
||||
```c++
|
||||
// Defines to set to use the Stm32Cube CMSIS FreeRTOS port
|
||||
#define USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION 1
|
||||
#define USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_THREAD_IMPLEMENTATION 1
|
||||
|
||||
#include "stm32cube-cmsis-freertos/eventqueue.h"
|
||||
```
|
BIN
src/xf/port/default-cmsis-os/README.pdf
Normal file
BIN
src/xf/port/default-cmsis-os/README.pdf
Normal file
Binary file not shown.
51
src/xf/port/default-cmsis-os/mutex-default.cpp
Normal file
51
src/xf/port/default-cmsis-os/mutex-default.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION != 0)
|
||||
|
||||
#include "mutex-default.h"
|
||||
|
||||
/**
|
||||
* @brief Implementation of interface::XFMutex::create method.
|
||||
*/
|
||||
interface::XFMutex * interface::XFMutex::create()
|
||||
{
|
||||
return new XFMutexDefault;
|
||||
}
|
||||
|
||||
XFMutexDefault::XFMutexDefault() :
|
||||
_mutexId(0)
|
||||
{
|
||||
memset(&_mutexDefinition,0,sizeof(_mutexDefinition));
|
||||
_mutexId = osMutexNew(&_mutexDefinition);
|
||||
assert(_mutexId);
|
||||
}
|
||||
|
||||
XFMutexDefault::~XFMutexDefault()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void XFMutexDefault::lock()
|
||||
{
|
||||
assert(_mutexId);
|
||||
osStatus status = osMutexWait(_mutexId, osWaitForever);
|
||||
assert(status == osOK);
|
||||
}
|
||||
|
||||
|
||||
void XFMutexDefault::unlock()
|
||||
{
|
||||
osStatus status = osMutexRelease(_mutexId);
|
||||
assert(status == osOK);
|
||||
}
|
||||
|
||||
|
||||
bool XFMutexDefault::tryLock(int32_t timeout /* = 0 */)
|
||||
{
|
||||
osStatus status = osMutexWait(_mutexId, timeout);
|
||||
return (status == osOK) ? true : false;
|
||||
}
|
||||
|
||||
#endif // USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION
|
38
src/xf/port/default-cmsis-os/mutex-default.h
Normal file
38
src/xf/port/default-cmsis-os/mutex-default.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef XF_MUTEX_DEFAULT_CMSIS_OS_H
|
||||
#define XF_MUTEX_DEFAULT_CMSIS_OS_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION != 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cmsis_os.h>
|
||||
#include "xf/interface/mutex.h"
|
||||
|
||||
/** @ingroup port_default_cmsis_os
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Default CMSIS-OS imlementation XFMutex interface.
|
||||
*
|
||||
*/
|
||||
class XFMutexDefault : public interface::XFMutex
|
||||
{
|
||||
public:
|
||||
XFMutexDefault();
|
||||
virtual ~XFMutexDefault();
|
||||
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
|
||||
virtual bool tryLock(int32_t timeout = 0);
|
||||
|
||||
protected:
|
||||
osMutexDef_t _mutexDefinition;
|
||||
osMutexId _mutexId;
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default_cmsis_os group
|
||||
#endif // USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION
|
||||
#endif // XF_MUTEX_DEFAULT_CMSIS_OS_H
|
6
src/xf/port/default-cmsis-os/port-default-cmsis-os.dox
Normal file
6
src/xf/port/default-cmsis-os/port-default-cmsis-os.dox
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
/** @defgroup port_default_cmsis_os CMSIS-OS Platform Default Port Classes
|
||||
*
|
||||
* CMSIS-OS platform default port classes.
|
||||
*
|
||||
*/
|
134
src/xf/port/default-cmsis-os/thread-default.cpp
Normal file
134
src/xf/port/default-cmsis-os/thread-default.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cassert>
|
||||
#include <string.h>
|
||||
#include "thread-default.h"
|
||||
|
||||
#if !defined(XFTHREAD_DEFAULT_STACK_SIZE)
|
||||
# define XFTHREAD_DEFAULT_STACK_SIZE 512
|
||||
#endif
|
||||
|
||||
//extern "C" const int uxTopUsedPriority;
|
||||
//const int __attribute__((used)) uxTopUsedPriority = configMAX_PRIORITIES - 1;
|
||||
|
||||
/**
|
||||
* Always keep threads after creation in suspended state.
|
||||
* Threads must be explicitly started with start()!
|
||||
*/
|
||||
|
||||
|
||||
/// Attributes structure for thread.
|
||||
/*
|
||||
typedef struct {
|
||||
const char *name; ///< name of the thread
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void *cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
void *stack_mem; ///< memory for stack
|
||||
uint32_t stack_size; ///< size of stack
|
||||
osPriority_t priority; ///< initial thread priority (default: osPriorityNormal)
|
||||
TZ_ModuleId_t tz_module; ///< TrustZone module identifier
|
||||
uint32_t reserved; ///< reserved (must be 0)
|
||||
} osThreadAttr_t;*/
|
||||
|
||||
XFThreadDefault::XFThreadDefault(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize /* = 0 */)
|
||||
{
|
||||
uint32_t threadStackSize = stackSize;
|
||||
|
||||
_pEntryMethodProvider = pProvider;
|
||||
_entryMethod = entryMethod;
|
||||
|
||||
strcpy(_threadName, threadName);
|
||||
|
||||
if (threadStackSize == 0)
|
||||
{
|
||||
threadStackSize = XFTHREAD_DEFAULT_STACK_SIZE;
|
||||
}
|
||||
|
||||
::memset(&_threadAttr, 0, sizeof(_threadAttr));
|
||||
|
||||
_threadAttr.name = _threadName;
|
||||
_threadAttr.priority = osPriorityNormal;
|
||||
_threadAttr.stack_size = threadStackSize;
|
||||
|
||||
_threadFunc = &threadEntryPoint;
|
||||
|
||||
_threadId = osThreadNew(_threadFunc, this, &_threadAttr);
|
||||
assert(_threadId); // Check if thread creation was successful
|
||||
|
||||
// Always keep threads after creation in suspended state.
|
||||
// Must be explicitly started with start();
|
||||
osThreadSuspend(_threadId);
|
||||
}
|
||||
|
||||
//static
|
||||
void XFThreadDefault::threadEntryPoint(void * param)
|
||||
{
|
||||
XFThreadDefault * pThis = (XFThreadDefault *)param;
|
||||
|
||||
(pThis->_pEntryMethodProvider->*pThis->_entryMethod)(param);
|
||||
}
|
||||
|
||||
void XFThreadDefault::start()
|
||||
{
|
||||
assert(_threadId != 0); // Check if thread was created
|
||||
osThreadResume(_threadId);
|
||||
}
|
||||
|
||||
void XFThreadDefault::stop()
|
||||
{
|
||||
osThreadTerminate(_threadId);
|
||||
}
|
||||
|
||||
void XFThreadDefault::setPriority(XFThreadPriority priority)
|
||||
{
|
||||
osPriority prio = osPriorityNormal;
|
||||
switch (priority)
|
||||
{
|
||||
case XF_THREAD_PRIO_LOW:
|
||||
prio = osPriorityLow;
|
||||
break;
|
||||
case XF_THREAD_PRIO_HIGH:
|
||||
prio = osPriorityHigh;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
osThreadSetPriority(_threadId, prio);
|
||||
}
|
||||
|
||||
XFThreadPriority XFThreadDefault::getPriority() const
|
||||
{
|
||||
const osPriority prio = osThreadGetPriority(_threadId);
|
||||
XFThreadPriority priority = XF_THREAD_PRIO_UNKNOWN;
|
||||
|
||||
switch (prio)
|
||||
{
|
||||
case osPriorityLow:
|
||||
priority = XF_THREAD_PRIO_LOW;
|
||||
break;
|
||||
case osPriorityNormal:
|
||||
priority = XF_THREAD_PRIO_NORMAL;
|
||||
break;
|
||||
case osPriorityHigh:
|
||||
priority = XF_THREAD_PRIO_HIGH;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
void XFThreadDefault::delay(uint32_t milliseconds)
|
||||
{
|
||||
osDelay(milliseconds);
|
||||
}
|
||||
|
||||
#endif // USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION
|
45
src/xf/port/default-cmsis-os/thread-default.h
Normal file
45
src/xf/port/default-cmsis-os/thread-default.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef XF_THREAD_DEFAULT_CMSIS_OS_H
|
||||
#define XF_THREAD_DEFAULT_CMSIS_OS_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION != 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cmsis_os.h>
|
||||
#include "xf/interface/thread.h"
|
||||
|
||||
class XFThreadDefault : public interface::XFThread
|
||||
{
|
||||
friend class XFResourceFactoryPort;
|
||||
|
||||
public:
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
|
||||
virtual void setPriority(XFThreadPriority priority);
|
||||
virtual XFThreadPriority getPriority() const;
|
||||
|
||||
virtual void delay(uint32_t milliseconds);
|
||||
|
||||
protected:
|
||||
XFThreadDefault(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize = 0);
|
||||
|
||||
static void threadEntryPoint(void * param);
|
||||
|
||||
protected:
|
||||
interface::XFThreadEntryPointProvider * _pEntryMethodProvider;
|
||||
interface::XFThread::EntryMethodBody _entryMethod;
|
||||
|
||||
osThreadAttr_t _threadAttr;
|
||||
osThreadFunc_t _threadFunc;
|
||||
char _threadName[32];
|
||||
|
||||
osThreadId _threadId;
|
||||
};
|
||||
|
||||
#endif // USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION
|
||||
#endif // XF_THREAD_DEFAULT_CMSIS_OS_H
|
42
src/xf/port/default-idf/README.md
Normal file
42
src/xf/port/default-idf/README.md
Normal file
@ -0,0 +1,42 @@
|
||||
# IDF (Interrupt Driven Framework) Platform Default Port
|
||||
|
||||
This folder provides a default implementation for IDF related XF classes.
|
||||
You can use these classes to construct an IDF based XF.
|
||||
|
||||
If these classes do not suit your needs, they can be reimplemented for
|
||||
your platform. Create an additional folder in the 'port' folder and
|
||||
implement there the classes you need for your platform.
|
||||
|
||||
# Available Default IDF Port Classes
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
| -------------- | ------------------------------------- | --------------------------------------- |
|
||||
| XFEventQueueDefault | xf/port/default-idf/eventqueue-default.cpp | USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION |
|
||||
| XFMutexDefault | xf/port/default-idf/mutex-default.cpp | USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION |
|
||||
|
||||
If you need more information about the classes mentioned above, please
|
||||
have a look into their header files and the doxygen comments in code.
|
||||
|
||||
# Example _config/xf-config.h_ File
|
||||
|
||||
Following you will find an example giving you a basic idea which define
|
||||
to set in the application specific _config/xf-config.h_ file.
|
||||
|
||||
The _IDF Stm32Cube_ port uses quite all default implementations:
|
||||
|
||||
```c++
|
||||
// Defines to set to use the IDF Stm32Cube port
|
||||
#define USE_XF_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_DISPATCHER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_RESOURCE_FACTORY_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION 1
|
||||
#define USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION 1
|
||||
|
||||
#define USE_XF_PORT_IDF_STM32CUBE_PORT_FUNCTIONS_IMPLEMENTATION 1
|
||||
|
||||
#include "default-idf/eventqueue-default.h"
|
||||
#ifdef __cplusplus
|
||||
using XFEventQueue = XFEventQueueDefault;
|
||||
#endif // __cplusplus
|
||||
```
|
BIN
src/xf/port/default-idf/README.pdf
Normal file
BIN
src/xf/port/default-idf/README.pdf
Normal file
Binary file not shown.
61
src/xf/port/default-idf/eventqueue-default.cpp
Normal file
61
src/xf/port/default-idf/eventqueue-default.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cassert>
|
||||
#include "eventqueue-default.h"
|
||||
|
||||
XFEventQueueDefault::XFEventQueueDefault()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
XFEventQueueDefault::~XFEventQueueDefault()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool XFEventQueueDefault::empty() const
|
||||
{
|
||||
return _queue.empty();
|
||||
}
|
||||
|
||||
bool XFEventQueueDefault::push(const XFEvent * pEvent, bool fromISR)
|
||||
{
|
||||
_mutex.lock();
|
||||
{
|
||||
_queue.push(pEvent);
|
||||
}
|
||||
_mutex.unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const XFEvent * XFEventQueueDefault::front()
|
||||
{
|
||||
const XFEvent * event;
|
||||
_mutex.lock();
|
||||
{
|
||||
event = _queue.front();
|
||||
}
|
||||
_mutex.unlock();
|
||||
return event;
|
||||
}
|
||||
|
||||
void XFEventQueueDefault::pop()
|
||||
{
|
||||
_mutex.lock();
|
||||
{
|
||||
_queue.pop();
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
bool XFEventQueueDefault::pend()
|
||||
{
|
||||
// Method cannot be used in an IDF! Waiting within
|
||||
// this method would block the whole XF
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION
|
51
src/xf/port/default-idf/eventqueue-default.h
Normal file
51
src/xf/port/default-idf/eventqueue-default.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef XF_EVENT_QUEUE_DEFAULT_H
|
||||
#define XF_EVENT_QUEUE_DEFAULT_H
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "config/xf-config.h"
|
||||
|
||||
#if (USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION != 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <queue>
|
||||
#include "xf/interface/eventqueue.h"
|
||||
#include "default-idf/mutex-default.h"
|
||||
|
||||
/** @ingroup port_default
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Default implementation of the event queue using a `std::queue` as container.
|
||||
*
|
||||
* This class does not provide a blocking pend() method. This means that this class
|
||||
* can be used in an IDF, but is not the right choice for a RTOS based XF.
|
||||
*/
|
||||
class XFEventQueueDefault : public interface::XFEventQueue
|
||||
{
|
||||
using Mutex = XFMutexDefault;
|
||||
public:
|
||||
XFEventQueueDefault();
|
||||
virtual ~XFEventQueueDefault();
|
||||
|
||||
// XFEventQueue interface implementation
|
||||
public:
|
||||
virtual bool empty() const; ///< Returns true if no event is in the queue.
|
||||
virtual bool push(const XFEvent * pEvent,
|
||||
bool fromISR = false); ///< Pushes the given event onto the queue.
|
||||
virtual const XFEvent * front(); ///< Returns pointer to next event to pop.
|
||||
virtual void pop(); ///< Pops the next event from the queue.
|
||||
///< Wait for the next event to arrive. Returns true if an event is in the queue.
|
||||
virtual bool pend();
|
||||
|
||||
protected:
|
||||
typedef std::queue<const XFEvent *> EventQueue; ///< Type of the event queue.
|
||||
|
||||
Mutex _mutex; ///< Mutex protecting access to _queue.
|
||||
EventQueue _queue; ///< Internal queue holding the events.
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default group
|
||||
#endif // USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION
|
||||
#endif // __cplusplus
|
||||
#endif // XF_EVENT_QUEUE_DEFAULT_H
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user