Initial commit
This commit is contained in:
14
src/app/ButtonEvent.cpp
Normal file
14
src/app/ButtonEvent.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* ButtonEvent.cpp
|
||||
*
|
||||
* Created on: 21 nov. 2023
|
||||
* Author: remi.heredero
|
||||
*/
|
||||
|
||||
#include <app/ButtonEvent.h>
|
||||
|
||||
ButtonEvent::ButtonEvent(int id, interface::XFReactive * pBehavior, uint8_t buttonId)
|
||||
: XFCustomEvent(id, pBehavior),
|
||||
buttonId_(buttonId) {
|
||||
}
|
||||
|
26
src/app/ButtonEvent.h
Normal file
26
src/app/ButtonEvent.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* ButtonEvent.h
|
||||
*
|
||||
* Created on: 21 nov. 2023
|
||||
* Author: remi.heredero
|
||||
*/
|
||||
|
||||
#ifndef BUTTONEVENT_H_
|
||||
#define BUTTONEVENT_H_
|
||||
|
||||
#include "xf/customevent.h"
|
||||
|
||||
class ButtonEvent : public XFCustomEvent {
|
||||
public:
|
||||
ButtonEvent(int id, interface::XFReactive * pBehavior, uint8_t buttonId);
|
||||
virtual ~ButtonEvent() = default;
|
||||
|
||||
protected:
|
||||
uint8_t buttonId_;
|
||||
|
||||
public:
|
||||
|
||||
inline uint8_t getButtonId() {return buttonId_; }
|
||||
};
|
||||
|
||||
#endif /* BUTTONEVENT_H_ */
|
80
src/app/buttoneventslogger.cpp
Normal file
80
src/app/buttoneventslogger.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* buttoneventslogger.cpp
|
||||
*
|
||||
* Created on: Nov 7, 2023
|
||||
* Author: remi.heredero
|
||||
*/
|
||||
|
||||
#include <app/buttoneventslogger.h>
|
||||
#include "trace/trace.h"
|
||||
#include "ButtonEvent.h"
|
||||
|
||||
ButtonEventsLogger::ButtonEventsLogger() {
|
||||
curentState_ = state::initial;
|
||||
}
|
||||
|
||||
void ButtonEventsLogger::onButtonShortPressed(ButtonIndex buttonIndex) {
|
||||
GEN(ButtonEvent(event::evButtonShortPressed, this, buttonIndex));
|
||||
}
|
||||
|
||||
void ButtonEventsLogger::onButtonLongPressed(ButtonIndex buttonIndex) {
|
||||
GEN(ButtonEvent(event::evButtonLongPressed, this, buttonIndex));
|
||||
}
|
||||
|
||||
XFEventStatus ButtonEventsLogger::processEvent() {
|
||||
eEventStatus eventStatus = XFEventStatus::NotConsumed;
|
||||
|
||||
ButtonEvent* ev = (ButtonEvent*)getCurrentEvent();
|
||||
XFEvent::XFEventType evType = ev->getEventType();
|
||||
int evid = ev->getId();
|
||||
|
||||
oldState_ = curentState_;
|
||||
changeState = false;
|
||||
|
||||
switch (curentState_) { //on state
|
||||
case state::initial:
|
||||
if(evType == XFEvent::Initial) {
|
||||
curentState_ = state::waitButtonPressed;
|
||||
changeState = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
}
|
||||
break;
|
||||
|
||||
case state::waitButtonPressed:
|
||||
if(evid == event::evButtonShortPressed){
|
||||
Trace::out("ButtonEventLogger: Button %d short pressed", ev->getButtonId());
|
||||
curentState_ = state::waitButtonPressed;
|
||||
changeState = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
}
|
||||
if(evid == event::evButtonLongPressed){
|
||||
Trace::out("ButtonEventLogger: Button %d long pressed", ev->getButtonId());
|
||||
curentState_ = state::waitButtonPressed;
|
||||
changeState = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(changeState) {
|
||||
switch (oldState_) { // onExit
|
||||
case state::initial:
|
||||
break;
|
||||
|
||||
case state::waitButtonPressed:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (curentState_) { // onEntry
|
||||
case state::initial:
|
||||
break;
|
||||
|
||||
case state::waitButtonPressed:
|
||||
break;
|
||||
|
||||
}
|
||||
changeState = false;
|
||||
}
|
||||
return eventStatus;
|
||||
}
|
||||
|
43
src/app/buttoneventslogger.h
Normal file
43
src/app/buttoneventslogger.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* buttoneventslogger.h
|
||||
*
|
||||
* Created on: Nov 7, 2023
|
||||
* Author: remi.heredero
|
||||
*/
|
||||
|
||||
#ifndef BUTTONEVENTSLOGGER_H_
|
||||
#define BUTTONEVENTSLOGGER_H_
|
||||
|
||||
#include "xf/behavior.h"
|
||||
#include "interface/buttoneventshandlerobserver.h"
|
||||
|
||||
class ButtonEventsLogger : public XFBehavior, public interface::ButtonEventsHandlerObserver {
|
||||
public:
|
||||
ButtonEventsLogger();
|
||||
virtual ~ButtonEventsLogger() = default;
|
||||
void onButtonShortPressed(ButtonIndex buttonIndex) override;
|
||||
void onButtonLongPressed(ButtonIndex buttonIndex) override;
|
||||
|
||||
|
||||
protected:
|
||||
XFEventStatus processEvent() override;
|
||||
|
||||
typedef enum {
|
||||
evButtonShortPressed,
|
||||
evButtonLongPressed
|
||||
} event;
|
||||
|
||||
typedef enum {
|
||||
initial,
|
||||
waitButtonPressed
|
||||
} state;
|
||||
|
||||
// TODO changeState and put next variable on behavior
|
||||
|
||||
state curentState_;
|
||||
state oldState_;
|
||||
bool changeState = false;
|
||||
|
||||
};
|
||||
|
||||
#endif /* BUTTONEVENTSLOGGER_H_ */
|
69
src/app/factory.cpp
Normal file
69
src/app/factory.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include "trace/trace.h"
|
||||
#include "touchgfxtask.h"
|
||||
#include "factory.h"
|
||||
#include "interface/buttonscontrollercallbackprovider.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
ButtonEventsLogger Factory::buttonEventLogger_;
|
||||
|
||||
Factory::Factory() {
|
||||
|
||||
}
|
||||
|
||||
// static
|
||||
void Factory::initialize() {
|
||||
Trace::initialize();
|
||||
|
||||
// TODO: Initialize factory attributes here
|
||||
|
||||
|
||||
#if defined(TOUCHGFX_ENABLED) && (TOUCHGFX_ENABLED != 0)
|
||||
getTouchGfxTask().initialize(_buttonEventsHandler);
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
void Factory::build() {
|
||||
Trace::out("Factory: Creating app components...");
|
||||
|
||||
// Start state machine(s)
|
||||
|
||||
buttonEventLogger_.startBehavior();
|
||||
ButtonsController::getInstance()->startBehavior();
|
||||
|
||||
ButtonsController::getInstance()->registerCallback (
|
||||
ButtonEventsHandler::getInstance(),
|
||||
(interface::ButtonsControllerCallbackProvider::CallbackMethod) &ButtonEventsHandler::onButtonChangeState
|
||||
);
|
||||
|
||||
buttonEventLogger_.startBehavior();
|
||||
ButtonEventsHandler::getInstance()->subscribe(&buttonEventLogger_);
|
||||
ButtonEventsHandler::getInstance()->startBehavior();
|
||||
|
||||
|
||||
|
||||
// TODO: Start state-machines here
|
||||
|
||||
#if defined(TOUCHGFX_ENABLED) && (TOUCHGFX_ENABLED != 0)
|
||||
getTouchGfxTask().start();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(TOUCHGFX_ENABLED) && (TOUCHGFX_ENABLED != 0)
|
||||
// static
|
||||
TouchGfxTask & Factory::getTouchGfxTask() {
|
||||
static TouchGfxTask touchGfxTask;
|
||||
return touchGfxTask;
|
||||
}
|
||||
#endif // TOUCHGFX_ENABLED
|
||||
|
||||
} /* namespace app */
|
||||
|
||||
void Factory_initialize() {
|
||||
app::Factory::initialize();
|
||||
}
|
||||
|
||||
void Factory_build() {
|
||||
app::Factory::build();
|
||||
}
|
54
src/app/factory.h
Normal file
54
src/app/factory.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef FACTORY_H
|
||||
#define FACTORY_H
|
||||
|
||||
//
|
||||
// What is seen only by the C++ compiler
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "config/touchgfx-config.h"
|
||||
#include "app/buttoneventslogger.h"
|
||||
#include "platform/f7-disco-gcc/board/ButtonsController.h"
|
||||
#include "mdw/button/ButtonEventsHandler.h"
|
||||
|
||||
// TODO: Add C++ specific includes here
|
||||
|
||||
namespace app {
|
||||
|
||||
/**
|
||||
* @brief Application factory responsible to create needed objects.
|
||||
*/
|
||||
class Factory {
|
||||
public:
|
||||
Factory();
|
||||
|
||||
static void initialize(); ///< Initializes the factory
|
||||
static void build(); ///< Creates components and initializes relations
|
||||
|
||||
#if defined(TOUCHGFX_ENABLED) && (TOUCHGFX_ENABLED != 0)
|
||||
static TouchGfxTask & getTouchGfxTask();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// TODO: Add static attributes here
|
||||
static ButtonEventsLogger buttonEventLogger_;
|
||||
};
|
||||
|
||||
} /* namespace app */
|
||||
#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 // FACTORY_H
|
48
src/app/touchgfxtask.cpp
Normal file
48
src/app/touchgfxtask.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "TouchGFX/App/app_touchgfx.h"
|
||||
#include "gui/common/FrontendHeap.hpp"
|
||||
#include "touchgfxtask.h"
|
||||
|
||||
#if defined(TOUCHGFX_ENABLED) && (TOUCHGFX_ENABLED != 0)
|
||||
|
||||
extern "C" void touchgfx_init();
|
||||
extern "C" void touchgfx_taskEntry();
|
||||
|
||||
TouchGfxTask::TouchGfxTask():
|
||||
interval_(20)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TouchGfxTask::initialize(ButtonEventsHandler & buttonEventsHandler)
|
||||
{
|
||||
touchgfx_init();
|
||||
|
||||
// Let the GUI model subscribe itself to button events
|
||||
FrontendHeap::getInstance().model.initialize(buttonEventsHandler);
|
||||
}
|
||||
|
||||
void TouchGfxTask::start()
|
||||
{
|
||||
startBehavior();
|
||||
}
|
||||
|
||||
XFEventStatus TouchGfxTask::processEvent()
|
||||
{
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::Initial)
|
||||
{
|
||||
scheduleTimeout(1, 20);
|
||||
}
|
||||
|
||||
// React on button events short and long pressed
|
||||
if (getCurrentEvent()->getEventType() == XFEvent::Timeout and
|
||||
getCurrentTimeout()->getId() == 1)
|
||||
{
|
||||
touchgfx_taskEntry();
|
||||
|
||||
scheduleTimeout(1, 20);
|
||||
}
|
||||
|
||||
return XFEventStatus::Consumed;
|
||||
}
|
||||
|
||||
#endif // TOUCHGFX_ENABLED
|
30
src/app/touchgfxtask.h
Normal file
30
src/app/touchgfxtask.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef TOUCHGFXTASK_H
|
||||
#define TOUCHGFXTASK_H
|
||||
|
||||
#include "config/touchgfx-config.h"
|
||||
|
||||
#if defined(TOUCHGFX_ENABLED) && (TOUCHGFX_ENABLED != 0)
|
||||
|
||||
#include "xf/behavior.h"
|
||||
#include "mdw/button/buttoneventshandler.h"
|
||||
|
||||
/**
|
||||
* @brief TouchGFX task used in IDF and/or bare-metal environments to drive LCD display.
|
||||
*/
|
||||
class TouchGfxTask : public XFBehavior
|
||||
{
|
||||
public:
|
||||
TouchGfxTask();
|
||||
|
||||
void initialize(ButtonEventsHandler & buttonEventsHandler);
|
||||
void start();
|
||||
|
||||
protected:
|
||||
XFEventStatus processEvent() override;
|
||||
|
||||
protected:
|
||||
const int32_t interval_;
|
||||
};
|
||||
|
||||
#endif // TOUCHGFX_ENABLED
|
||||
#endif // TOUCHGFXTASK_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);
|
||||
}
|
18
src/event/evbuttonirq.h
Normal file
18
src/event/evbuttonirq.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef EVBUTTONIRQ_H
|
||||
#define EVBUTTONIRQ_H
|
||||
|
||||
#include "xf/customevent.h"
|
||||
#include "events.h"
|
||||
|
||||
/**
|
||||
* @brief Event used in GPIO ISR (interrupt service routine).
|
||||
*
|
||||
* Is send on rising and falling edge of the signal.
|
||||
*/
|
||||
class evButtonIrq : public XFCustomEvent
|
||||
{
|
||||
public:
|
||||
evButtonIrq();
|
||||
};
|
||||
|
||||
#endif // EVBUTTONIRQ_H
|
8
src/event/evbuttonpressed.cpp
Normal file
8
src/event/evbuttonpressed.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "events.h"
|
||||
#include "evbuttonpressed.h"
|
||||
|
||||
evButtonPressed::evButtonPressed() :
|
||||
XFCustomEvent(evButtonPressedId)
|
||||
{
|
||||
|
||||
}
|
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"
|
||||
|
||||
/**
|
||||
* @brief Event send when button is pressed.
|
||||
*
|
||||
* Used internally in state-machine handling one particular button.
|
||||
*/
|
||||
class evButtonPressed : public XFCustomEvent
|
||||
{
|
||||
public:
|
||||
evButtonPressed();
|
||||
};
|
||||
|
||||
#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)
|
||||
{
|
||||
|
||||
}
|
18
src/event/evbuttonreleased.h
Normal file
18
src/event/evbuttonreleased.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef EVBUTTONRELEASED_H
|
||||
#define EVBUTTONRELEASED_H
|
||||
|
||||
#include "xf/customevent.h"
|
||||
#include "events.h"
|
||||
|
||||
/**
|
||||
* @brief Event send when button is released.
|
||||
*
|
||||
* Used internally in state-machine handling one particular button.
|
||||
*/
|
||||
class evButtonReleased : public XFCustomEvent
|
||||
{
|
||||
public:
|
||||
evButtonReleased();
|
||||
};
|
||||
|
||||
#endif // EVBUTTONRELEASED_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
|
32
src/interface/buttoneventshandlerobserver.h
Normal file
32
src/interface/buttoneventshandlerobserver.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef INTERFACE_BUTTONEVENTSHANDLER_OBSERVER_H
|
||||
#define INTERFACE_BUTTONEVENTSHANDLER_OBSERVER_H
|
||||
|
||||
#include "buttoneventshandlersubject.h"
|
||||
|
||||
class ButtonEventsHandler;
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface to be provided by the class who wants to receive button short/long pressed notifications.
|
||||
*/
|
||||
class ButtonEventsHandlerObserver
|
||||
{
|
||||
friend class ButtonEventsHandlerSubject;
|
||||
friend class ::ButtonEventsHandler;
|
||||
|
||||
public:
|
||||
typedef ButtonEventsHandlerSubject::ButtonIndex ButtonIndex;
|
||||
|
||||
virtual ~ButtonEventsHandlerObserver() {}
|
||||
|
||||
protected:
|
||||
virtual void onButtonShortPressed(ButtonIndex buttonIndex) = 0; ///< @brief Called by the subject upon a button short pressed.
|
||||
virtual void onButtonLongPressed(ButtonIndex buttonIndex) = 0; ///< @brief Called by the subject upon a button long pressed.
|
||||
|
||||
protected:
|
||||
ButtonEventsHandlerObserver() {} ///< @brief Not allowing to instantiate object of interface.
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // INTERFACE_BUTTONEVENTSHANDLER_OBSERVER_H
|
33
src/interface/buttoneventshandlersubject.h
Normal file
33
src/interface/buttoneventshandlersubject.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef INTERFACE_BUTTONEVENTSHANDLER_SUBJECT_H
|
||||
#define INTERFACE_BUTTONEVENTSHANDLER_SUBJECT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace interface {
|
||||
|
||||
class ButtonEventsHandlerObserver;
|
||||
|
||||
/**
|
||||
* @brief Interface for the class who handles and notifies button short/long pressed events.
|
||||
*/
|
||||
class ButtonEventsHandlerSubject
|
||||
{
|
||||
public:
|
||||
typedef uint8_t ButtonIndex;
|
||||
|
||||
virtual ~ButtonEventsHandlerSubject() {}
|
||||
|
||||
public:
|
||||
virtual bool subscribe(ButtonEventsHandlerObserver * observer) = 0; ///< @brief Registers a new observer. Returns true on success.
|
||||
virtual void unsubscribe(ButtonEventsHandlerObserver * observer) = 0; ///< @brief Un-subscribes a registered observer.
|
||||
|
||||
protected:
|
||||
virtual void notifyButtonShortPressed(ButtonIndex buttonIndex) = 0; ///< @brief Notifies observers about a button short pressed.
|
||||
virtual void notifyButtonLongPressed(ButtonIndex buttonIndex) = 0; ///< @brief Notifies observers about a button long pressed.
|
||||
|
||||
protected:
|
||||
ButtonEventsHandlerSubject() {} ///< @brief Not allowing to instantiate object of interface.
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // INTERFACE_BUTTONEVENTSHANDLER_SUBJECT_H
|
27
src/interface/buttonirq.h
Normal file
27
src/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
|
30
src/interface/buttonscontrollercallbackcaller.h
Normal file
30
src/interface/buttonscontrollercallbackcaller.h
Normal file
@ -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
|
32
src/interface/buttonscontrollercallbackprovider.h
Normal file
32
src/interface/buttonscontrollercallbackprovider.h
Normal file
@ -0,0 +1,32 @@
|
||||
#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
|
112
src/mdw/button/ButtonEventsHandler.cpp
Normal file
112
src/mdw/button/ButtonEventsHandler.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* ButtonEventsHandler.cpp
|
||||
*
|
||||
* Created on: 19 nov. 2023
|
||||
* Author: remi.heredero
|
||||
*/
|
||||
|
||||
#include <button/ButtonEventsHandler.h>
|
||||
#include "trace/trace.h"
|
||||
#include "board/ButtonsController.h"
|
||||
|
||||
|
||||
ButtonEventsHandler::ButtonEventsHandler() {
|
||||
for(uint8_t i = 0; i< MAX_OBSERVER; i++) {
|
||||
observer_[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ButtonEventsHandler* ButtonEventsHandler::getInstance() {
|
||||
static ButtonEventsHandler buttonEventsHandler_;
|
||||
return &buttonEventsHandler_;
|
||||
}
|
||||
|
||||
XFEventStatus ButtonEventsHandler::processEvent() {
|
||||
eEventStatus eventStatus = XFEventStatus::Unknown;
|
||||
|
||||
const XFEvent* ev = getCurrentEvent();
|
||||
XFEvent::XFEventType evType = ev->getEventType();
|
||||
int evid = ev->getId();
|
||||
|
||||
oldState_ = currentState_;
|
||||
changeState_ = false;
|
||||
|
||||
switch (currentState_) {
|
||||
case state::initial:
|
||||
if(evType == XFEvent::Initial) {
|
||||
currentState_ = state::run;
|
||||
changeState_ = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
}
|
||||
break;
|
||||
|
||||
case state::run:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if(changeState_) {
|
||||
switch (oldState_) { // onExit
|
||||
case state::initial:
|
||||
break;
|
||||
|
||||
case state::run:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (currentState_) { // onEntry
|
||||
case state::initial:
|
||||
break;
|
||||
|
||||
case state::run:
|
||||
buttonStateSm_[0].startBehavior();
|
||||
buttonStateSm_[1].startBehavior();
|
||||
buttonStateSm_[2].startBehavior();
|
||||
buttonStateSm_[3].startBehavior();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return eventStatus;
|
||||
}
|
||||
|
||||
void ButtonEventsHandler::onButtonChangeState(uint16_t buttonIndex, bool pressed) {
|
||||
if(pressed) {
|
||||
buttonStateSm_[buttonIndex].genButtonPressed();
|
||||
} else {
|
||||
buttonStateSm_[buttonIndex].genButtonReleased();
|
||||
}
|
||||
}
|
||||
|
||||
bool ButtonEventsHandler::subscribe(interface::ButtonEventsHandlerObserver *observer) {
|
||||
for(uint8_t i = 0; i < MAX_OBSERVER; i++) {
|
||||
if (observer_[i] == nullptr) {
|
||||
observer_[i] = observer;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ButtonEventsHandler::unsubscribe(interface::ButtonEventsHandlerObserver *observer) {
|
||||
for(uint8_t i = 0; i < MAX_OBSERVER; i++) {
|
||||
if (observer_[i] == observer) {
|
||||
observer_[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonEventsHandler::notifyButtonShortPressed(ButtonIndex buttonIndex) {
|
||||
for(uint8_t i = 0; i < MAX_OBSERVER; i++) {
|
||||
if (observer_[i] != nullptr) {
|
||||
observer_[i]->onButtonShortPressed(buttonIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonEventsHandler::notifyButtonLongPressed(ButtonIndex buttonIndex) {
|
||||
for(uint8_t i = 0; i < MAX_OBSERVER; i++) {
|
||||
if (observer_[i] != nullptr) {
|
||||
observer_[i]->onButtonLongPressed(buttonIndex);
|
||||
}
|
||||
}
|
||||
}
|
52
src/mdw/button/ButtonEventsHandler.h
Normal file
52
src/mdw/button/ButtonEventsHandler.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* ButtonEventsHandler.h
|
||||
*
|
||||
* Created on: 19 nov. 2023
|
||||
* Author: remi.heredero
|
||||
*/
|
||||
|
||||
#ifndef BUTTON_BUTTONEVENTSHANDLER_H_
|
||||
#define BUTTON_BUTTONEVENTSHANDLER_H_
|
||||
|
||||
#include "xf/behavior.h"
|
||||
#include "interface/buttonscontrollercallbackprovider.h"
|
||||
#include "interface/buttoneventshandlersubject.h"
|
||||
#include "interface/buttoneventshandlerobserver.h"
|
||||
#include "button/ButtonStateSm.h"
|
||||
|
||||
#define MAX_OBSERVER 5
|
||||
|
||||
class ButtonEventsHandler : public XFBehavior, public interface::ButtonsControllerCallbackProvider, public interface::ButtonEventsHandlerSubject {
|
||||
public:
|
||||
~ButtonEventsHandler() override = default;
|
||||
static ButtonEventsHandler* getInstance();
|
||||
|
||||
void onButtonChangeState(uint16_t buttonIndex, bool pressed);
|
||||
|
||||
virtual bool subscribe(interface::ButtonEventsHandlerObserver* observer);
|
||||
virtual void unsubscribe(interface::ButtonEventsHandlerObserver* observer);
|
||||
|
||||
virtual void notifyButtonShortPressed(ButtonIndex buttonIndex);
|
||||
virtual void notifyButtonLongPressed(ButtonIndex buttonIndex);
|
||||
|
||||
protected:
|
||||
ButtonEventsHandler();
|
||||
XFEventStatus processEvent() override;
|
||||
|
||||
typedef enum {
|
||||
initial,
|
||||
run
|
||||
} state ;
|
||||
|
||||
state currentState_;
|
||||
state oldState_;
|
||||
bool changeState_;
|
||||
|
||||
interface::ButtonEventsHandlerObserver* observer_[MAX_OBSERVER];
|
||||
ButtonStateSm buttonStateSm_[4];
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* BUTTON_BUTTONEVENTSHANDLER_H_ */
|
127
src/mdw/button/ButtonStateSm.cpp
Normal file
127
src/mdw/button/ButtonStateSm.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* ButtonStateSm.cpp
|
||||
*
|
||||
* Created on: 19 nov. 2023
|
||||
* Author: remi.heredero
|
||||
*/
|
||||
|
||||
#include <button/ButtonStateSm.h>
|
||||
#include "mdw/button/ButtonEventsHandler.h"
|
||||
|
||||
//TODO start State Machine. For that, turn ButtonEventsHandler to a State Machine (Initial, run)
|
||||
ButtonStateSm::ButtonStateSm()
|
||||
: buttonIndex_(getNbInstance()) {
|
||||
currentState_ = state::initial;
|
||||
}
|
||||
|
||||
uint8_t ButtonStateSm::getNbInstance(){
|
||||
static uint8_t nbInstances = 0;
|
||||
return nbInstances++;
|
||||
}
|
||||
|
||||
void ButtonStateSm::genButtonPressed() {
|
||||
GEN(XFEvent(XFEvent::Event, event::evButtonPressed, this));
|
||||
}
|
||||
void ButtonStateSm::genButtonReleased() {
|
||||
GEN(XFEvent(XFEvent::Event, event::evButtonReleased, this));
|
||||
}
|
||||
|
||||
XFEventStatus ButtonStateSm::processEvent() {
|
||||
eEventStatus eventStatus = XFEventStatus::Unknown;
|
||||
|
||||
const XFEvent* ev = getCurrentEvent();
|
||||
XFEvent::XFEventType evType = ev->getEventType();
|
||||
int evid = ev->getId();
|
||||
|
||||
oldState_ = currentState_;
|
||||
changeState_ = false;
|
||||
|
||||
switch (currentState_) {
|
||||
case state::initial:
|
||||
if(evType == XFEvent::Initial) {
|
||||
currentState_ = state::waitButtonPressed;
|
||||
changeState_ = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
}
|
||||
break;
|
||||
|
||||
case state::waitButtonPressed:
|
||||
if(evid == event::evButtonPressed) {
|
||||
currentState_ = state::buttonPressed;
|
||||
changeState_ = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
scheduleTimeout(event::evTimeout, 1000);
|
||||
}
|
||||
break;
|
||||
|
||||
case state::buttonPressed:
|
||||
if(evid == event::evButtonReleased) {
|
||||
currentState_ = state::buttonShortPressed;
|
||||
changeState_ = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
unscheduleTimeout(event::evTimeout);
|
||||
}
|
||||
if(evid == event::evTimeout) {
|
||||
currentState_ = state::buttonLongPressed;
|
||||
changeState_ = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
}
|
||||
GEN(XFNullTransition(this));
|
||||
break;
|
||||
|
||||
case state::buttonShortPressed:
|
||||
if(evType == XFEvent::XFEventType::NullTransition) {
|
||||
currentState_ = state::waitButtonPressed;
|
||||
changeState_ = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
}
|
||||
break;
|
||||
|
||||
case state::buttonLongPressed:
|
||||
if(evType == XFEvent::XFEventType::NullTransition) {
|
||||
currentState_ = state::waitButtonPressed;
|
||||
changeState_ = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(changeState_) {
|
||||
switch (oldState_) { // onExit
|
||||
case state::initial:
|
||||
break;
|
||||
|
||||
case state::waitButtonPressed:
|
||||
break;
|
||||
|
||||
case state::buttonPressed:
|
||||
break;
|
||||
|
||||
case state::buttonShortPressed:
|
||||
break;
|
||||
|
||||
case state::buttonLongPressed:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (currentState_) {
|
||||
case state::initial:
|
||||
break;
|
||||
|
||||
case state::waitButtonPressed:
|
||||
break;
|
||||
|
||||
case state::buttonPressed:
|
||||
break;
|
||||
|
||||
case state::buttonShortPressed:
|
||||
ButtonEventsHandler::getInstance()->notifyButtonShortPressed(buttonIndex_);
|
||||
break;
|
||||
|
||||
case state::buttonLongPressed:
|
||||
ButtonEventsHandler::getInstance()->notifyButtonLongPressed(buttonIndex_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return eventStatus;
|
||||
}
|
48
src/mdw/button/ButtonStateSm.h
Normal file
48
src/mdw/button/ButtonStateSm.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* ButtonStateSm.h
|
||||
*
|
||||
* Created on: 19 nov. 2023
|
||||
* Author: remi.heredero
|
||||
*/
|
||||
|
||||
#ifndef BUTTON_BUTTONSTATESM_H_
|
||||
#define BUTTON_BUTTONSTATESM_H_
|
||||
|
||||
#include "xf/behavior.h"
|
||||
|
||||
class ButtonStateSm : public XFBehavior {
|
||||
public:
|
||||
ButtonStateSm();
|
||||
virtual ~ButtonStateSm() = default;
|
||||
void genButtonPressed();
|
||||
void genButtonReleased();
|
||||
|
||||
protected:
|
||||
XFEventStatus processEvent() override;
|
||||
|
||||
typedef enum {
|
||||
evButtonPressed,
|
||||
evButtonReleased,
|
||||
evTimeout
|
||||
} event;
|
||||
|
||||
typedef enum {
|
||||
initial,
|
||||
waitButtonPressed,
|
||||
buttonPressed,
|
||||
buttonShortPressed,
|
||||
buttonLongPressed
|
||||
} state;
|
||||
|
||||
state currentState_;
|
||||
state oldState_;
|
||||
bool changeState_;
|
||||
const uint8_t buttonIndex_;
|
||||
|
||||
private:
|
||||
static uint8_t getNbInstance();
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* BUTTON_BUTTONSTATESM_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
|
133
src/platform/f7-disco-gcc/board/ButtonsController.cpp
Normal file
133
src/platform/f7-disco-gcc/board/ButtonsController.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* ButtonsController.cpp
|
||||
*
|
||||
* Created on: 14 nov. 2023
|
||||
* Author: remi.heredero
|
||||
*/
|
||||
|
||||
#include <board/ButtonsController.h>
|
||||
#include "trace/trace.h"
|
||||
#include "main.h"
|
||||
|
||||
ButtonsController::ButtonsController() {
|
||||
curentState_ = state::initial;
|
||||
cbProvider = nullptr;
|
||||
cbMethod = nullptr;
|
||||
};
|
||||
|
||||
ButtonsController* ButtonsController::getInstance() {
|
||||
static ButtonsController buttonsController_;
|
||||
return &buttonsController_;
|
||||
}
|
||||
|
||||
void ButtonsController::onIrq() {
|
||||
GEN(XFEvent(XFEvent::XFEventType::Event, event::evButtonIrq, this));
|
||||
}
|
||||
|
||||
bool ButtonsController::registerCallback(
|
||||
interface::ButtonsControllerCallbackProvider *callbackProvider,
|
||||
interface::ButtonsControllerCallbackProvider::CallbackMethod callbackMethod) {
|
||||
|
||||
if(callbackProvider == nullptr) return false;
|
||||
if(callbackMethod == nullptr) return false;
|
||||
|
||||
cbProvider = callbackProvider;
|
||||
cbMethod = callbackMethod;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
XFEventStatus ButtonsController::processEvent() {
|
||||
eEventStatus eventStatus = XFEventStatus::Unknown;
|
||||
|
||||
const XFEvent* ev = getCurrentEvent();
|
||||
XFEvent::XFEventType evType = ev->getEventType();
|
||||
int evid = ev->getId();
|
||||
|
||||
oldState_ = curentState_;
|
||||
changeState = false;
|
||||
|
||||
switch (curentState_) {
|
||||
case state::initial:
|
||||
if(evType == XFEvent::Initial) {
|
||||
curentState_ = state::checkButtons;
|
||||
changeState = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
}
|
||||
break;
|
||||
|
||||
case state::checkButtons:
|
||||
if (evid == event::evButtonIrq) {
|
||||
curentState_ = state::debounce;
|
||||
changeState = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
}
|
||||
break;
|
||||
|
||||
case state::debounce:
|
||||
if (evid == event::evTimeout) {
|
||||
curentState_ = state::checkButtons;
|
||||
changeState = true;
|
||||
eventStatus = XFEventStatus::Consumed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(changeState) {
|
||||
switch (oldState_) { // onExit
|
||||
case state::initial:
|
||||
break;
|
||||
|
||||
case state::checkButtons:
|
||||
break;
|
||||
|
||||
case state::debounce:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
switch (curentState_) { // onEntry
|
||||
case state::initial:
|
||||
break;
|
||||
|
||||
case state::checkButtons:
|
||||
|
||||
if(cbProvider != nullptr) {
|
||||
|
||||
newState[0] = HAL_GPIO_ReadPin(BUTTON0_GPIO_Port, BUTTON0_Pin);
|
||||
newState[1] = HAL_GPIO_ReadPin(BUTTON1_GPIO_Port, BUTTON1_Pin);
|
||||
newState[2] = HAL_GPIO_ReadPin(BUTTON2_GPIO_Port, BUTTON2_Pin);
|
||||
newState[3] = HAL_GPIO_ReadPin(BUTTON3_GPIO_Port, BUTTON3_Pin);
|
||||
|
||||
if(newState[0] != buttonState[0]) {
|
||||
buttonState[0] = newState[0];
|
||||
(cbProvider->*cbMethod)(0, !buttonState[0]);
|
||||
|
||||
}
|
||||
|
||||
if(newState[1] != buttonState[1]) {
|
||||
buttonState[1] = newState[1];
|
||||
(cbProvider->*cbMethod)(1, !buttonState[1]);
|
||||
}
|
||||
|
||||
if(newState[2] != buttonState[2]) {
|
||||
buttonState[2] = newState[2];
|
||||
(cbProvider->*cbMethod)(2, !buttonState[2]);
|
||||
}
|
||||
|
||||
if(newState[3] != buttonState[3]) {
|
||||
buttonState[3] = newState[3];
|
||||
(cbProvider->*cbMethod)(3, !buttonState[3]);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case state::debounce:
|
||||
scheduleTimeout(event::evTimeout, 100);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return eventStatus;
|
||||
}
|
52
src/platform/f7-disco-gcc/board/ButtonsController.h
Normal file
52
src/platform/f7-disco-gcc/board/ButtonsController.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* ButtonsController.h
|
||||
*
|
||||
* Created on: 14 nov. 2023
|
||||
* Author: remi.heredero
|
||||
*/
|
||||
|
||||
#ifndef F7_DISCO_GCC_BOARD_BUTTONSCONTROLLER_H_
|
||||
#define F7_DISCO_GCC_BOARD_BUTTONSCONTROLLER_H_
|
||||
|
||||
#include "xf/behavior.h"
|
||||
#include "interface/buttonirq.h"
|
||||
#include "interface/buttonscontrollercallbackcaller.h"
|
||||
|
||||
class ButtonsController : public XFBehavior, public interface::ButtonIrq, public interface::ButtonsControllerCallbackCaller {
|
||||
public:
|
||||
~ButtonsController() override = default;
|
||||
static ButtonsController* getInstance();
|
||||
|
||||
protected:
|
||||
ButtonsController();
|
||||
XFEventStatus processEvent() override;
|
||||
|
||||
typedef enum {
|
||||
evButtonIrq = 1,
|
||||
evTimeout
|
||||
} event;
|
||||
|
||||
typedef enum {
|
||||
initial,
|
||||
checkButtons,
|
||||
debounce
|
||||
} state;
|
||||
|
||||
state curentState_;
|
||||
state oldState_;
|
||||
bool changeState = false;
|
||||
interface::ButtonsControllerCallbackProvider* cbProvider;
|
||||
interface::ButtonsControllerCallbackProvider::CallbackMethod cbMethod;
|
||||
bool newState[4];
|
||||
bool buttonState[4];
|
||||
|
||||
public:
|
||||
virtual void onIrq() override;
|
||||
virtual bool registerCallback(
|
||||
interface::ButtonsControllerCallbackProvider *callbackProvider,
|
||||
interface::ButtonsControllerCallbackProvider::CallbackMethod callbackMethod)
|
||||
override;
|
||||
|
||||
};
|
||||
|
||||
#endif /* F7_DISCO_GCC_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
|
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
|
33
src/xf/README.md
Normal file
33
src/xf/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# The XF Project
|
||||
XF project used by other projects as _git submodule_.
|
||||
|
||||
> Note
|
||||
>
|
||||
> This is not the original XF project!
|
||||
|
||||
## Introduction
|
||||
|
||||
This is more of a 'git fork' of the orignial project located in the
|
||||
[XF laboratory project](https://gitlab.hevs.ch/course/ptr/lab/xf/tree/master/01-work/src/xf).
|
||||
|
||||
The XF is used by following projects as _git submodule_:
|
||||
- [ButtonManager Project](https://gitlab.hevs.ch/course/ptr/lab/buttonmanager/tree/develop/01-work/ButtonManager/src)
|
||||
- [RealtimeOscilloscope Project](https://gitlab.hevs.ch/course/ptr/lab/realtime-oscilloscope/tree/develop/01-work/RealtimeOscilloscope/src)
|
||||
|
||||
> Note
|
||||
>
|
||||
> The XF project should never be hand out to the students, because it contains
|
||||
> already the solution for the XF laboratory!
|
||||
>
|
||||
> For the XF laboratory, provide the [work.zip](https://gitlab.hevs.ch/course/ptr/lab/xf/tree/master/03-release)
|
||||
> to the students instead.
|
||||
|
||||
## Update XF Project to latest XF Release
|
||||
- Checkout _develop_ branch
|
||||
- Remove file `xf-core.pri`
|
||||
- Remove all folders (config, core, etc.)
|
||||
- Keep files `README.md` and `.git` files
|
||||
- Checkout _master_ branch from [XF laboratory project](https://gitlab.hevs.ch/course/ptr/lab/xf/tree/master/01-work/src/xf)
|
||||
- Copy paste the code into this project
|
||||
- Commit changes
|
||||
- Make a release with the same tag given in the _XF laboratory project_
|
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
|
40
src/xf/port/default-idf/mutex-default.cpp
Normal file
40
src/xf/port/default-idf/mutex-default.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION != 0)
|
||||
|
||||
#include "critical/critical.h" // Provided by the platform used
|
||||
#include "mutex-default.h"
|
||||
|
||||
/**
|
||||
* @brief Implementation of interface::XFMutex::create method.
|
||||
*/
|
||||
interface::XFMutex * interface::XFMutex::create()
|
||||
{
|
||||
return new XFMutexDefault;
|
||||
}
|
||||
|
||||
XFMutexDefault::XFMutexDefault()
|
||||
{
|
||||
}
|
||||
|
||||
XFMutexDefault::~XFMutexDefault()
|
||||
{
|
||||
}
|
||||
|
||||
void XFMutexDefault::lock()
|
||||
{
|
||||
critical_enter();
|
||||
}
|
||||
|
||||
|
||||
void XFMutexDefault::unlock()
|
||||
{
|
||||
critical_exit();
|
||||
}
|
||||
|
||||
bool XFMutexDefault::tryLock(int32_t timeout /* = 0 */)
|
||||
{
|
||||
return true; // Always allow
|
||||
}
|
||||
|
||||
#endif // USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION
|
37
src/xf/port/default-idf/mutex-default.h
Normal file
37
src/xf/port/default-idf/mutex-default.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef XF_MUTEX_DEFAULT_IDF_H
|
||||
#define XF_MUTEX_DEFAULT_IDF_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION != 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include "xf/interface/mutex.h"
|
||||
|
||||
/** @ingroup port_default_idf
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Default IDF imlementation XFMutex interface.
|
||||
*
|
||||
* This class uses `enterCritical()` and `exitCritical()`
|
||||
* functions which must be provided by the platform.
|
||||
* Therefore, this mutex implementation can be used
|
||||
* in Embedded Systems without OS.
|
||||
*/
|
||||
class XFMutexDefault : public interface::XFMutex
|
||||
{
|
||||
public:
|
||||
XFMutexDefault();
|
||||
virtual ~XFMutexDefault();
|
||||
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
|
||||
virtual bool tryLock(int32_t timeout = 0);
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default_idf group
|
||||
#endif // USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION
|
||||
#endif // XF_MUTEX_DEFAULT_IDF_H
|
6
src/xf/port/default-idf/port-default-idf.dox
Normal file
6
src/xf/port/default-idf/port-default-idf.dox
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
/** @defgroup port_default_idf IDF Platform Default Port Classes
|
||||
*
|
||||
* IDF platform default port classes.
|
||||
*
|
||||
*/
|
46
src/xf/port/default-qt/README.md
Normal file
46
src/xf/port/default-qt/README.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Qt Platform Default Port
|
||||
|
||||
This folder provides a default implementation for Qt platform
|
||||
related XF classes. You can use these classes to construct a Qt
|
||||
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 Qt Port Classes
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
| -- | -- | -- |
|
||||
| XFEventQueueDefault | xf/port/default-qt/eventqueue-default.cpp | USE_XF_EVENT_QUEUE_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XFMutexDefault | xf/port/default-qt/mutex-default.cpp | USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XFThreadDefault | xf/port/default-qt/thread-default.cpp | USE_XF_THREAD_DEFAULT_QT_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 Qt_ port uses these classes:
|
||||
|
||||
```c++
|
||||
// Defines to set to use the IDF Qt port
|
||||
#define USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_EVENT_QUEUE_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_CLASS_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_FUNCTIONS_DEFAULT_QT_IMPLEMENTATION 1
|
||||
|
||||
#define USE_XF_PORT_IDF_QT_RESOURCE_FACTORY_IMPLEMENTATION 1
|
||||
|
||||
#include "default-qt/eventqueue-default.h"
|
||||
#ifdef __cplusplus
|
||||
// Force to take the XFEventQueueDefault implementation for the event queue
|
||||
using XFEventQueue = XFEventQueueDefault;
|
||||
#endif // __cplusplus
|
||||
```
|
BIN
src/xf/port/default-qt/README.pdf
Normal file
BIN
src/xf/port/default-qt/README.pdf
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user