polymurph 4 years ago
commit 9139565f1d

2
.gitignore vendored

@ -2,3 +2,5 @@
# vim swp files
*.swp
./.vscode/*

@ -0,0 +1,47 @@
{
"files.associations": {
"array": "cpp",
"atomic": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"typeinfo": "cpp"
}
}

@ -0,0 +1,29 @@
cpp_src = $(wildcard *.cpp)
cpp_src += $(wildcard ./utils/*.cpp)
cpp_src += $(wildcard ./driver/*.cpp)
cpp_obj = $(cpp_src:.cpp=.o)
c_obj = $(c_src:.c=.o)
CC = g++
CFLAGS = -Wall -pedantic -li2c
LDFLAGS =
EXEC = runtest
all : $(EXEC)
$(EXEC): $(cpp_obj) $(c_obj)
$(CC) -o $@ $^ $(LDFLAGS)
debug : $(EXEC)
$(EXEC): $(cpp_obj) $(c_obj)
$(CC) -g -o $@ $^ $(LDFLAGS)
clean:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear
cleanall:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear

@ -0,0 +1,148 @@
#include <memory>
#include <iostream>
// https://www.modernescpp.com/index.php/c-is-still-lazy
//
// CRTP base class of pin
//
/*
avoiding virtual call (static polymorphism)
*/
template <typename Derived>
struct PinBase
{
void set(bool logic)
{
static_cast<Derived*>(this)->setImp(logic);
}
void toggle()
{
static_cast<Derived*>(this)->toggleImp();
}
bool get(void)
{
return static_cast<Derived*>(this)->getImp();
}
private:
//
// base implementations
//
void setImp()
{
std::cout << "base implementation of set()!" << std::endl;
}
void toggleImp()
{
std::cout << "base implementation of toggle()!" << std::endl;
}
bool getImp(void)
{
std::cout << "base implementation of get()!" << std::endl;
return true;
}
};
//
// implementations
//
struct STM32_Pin : PinBase<STM32_Pin>
{
STM32_Pin()
{
std::cout << "created STM32_Pin" << std::endl;
}
void setImp(bool logic)
{
std::cout << "stm32 pin set to " << logic << std::endl;
}
void toggleImp()
{
std::cout << "toggled stm32 pin" << std::endl;
}
bool getImp()
{
return true;
}
void STM32_stuff()
{
std::cout << "STM_32 specific stuff" << std::endl;
}
};
struct AVR_Pin : PinBase<AVR_Pin>
{
AVR_Pin()
{
std::cout << "created AVR_Pin" << std::endl;
}
void setImp(bool logic)
{
std::cout << "AVR pin set to " << logic << std::endl;
}
void toggleImp()
{
std::cout << "toggled AVR pin" << std::endl;
}
bool getImp()
{
return true;
}
void avr_stuff()
{
std::cout << "AVR specific stuff" << std::endl;
}
};
template<typename T>
void foo(T& base)
{
base.set(true);
base.set(false);
base.toggle();
}
template<typename T>
void baa(PinBase<T>& pin)
{
pin.toggle();
//foo(pin);
}
int main(void)
{
STM32_Pin pin1;
AVR_Pin pin2;
pin1.STM32_stuff();
pin2.avr_stuff();
foo(pin1);
foo(pin2);
baa(pin1);
while(1);
return 0;
}

Binary file not shown.

@ -0,0 +1,204 @@
#include <memory>
#include <iostream>
// https://www.modernescpp.com/index.php/c-is-still-lazy
//
// CRTP base class of pin
//
/*
avoiding virtual call (static polymorphism)
*/
struct IPin
{
void set(bool logic);
void toggle();
bool get();
};
template <typename Derived>
struct PinBase : public IPin
{
void set(bool logic)
{
static_cast<Derived*>(this)->setImp(logic);
}
void toggle()
{
static_cast<Derived*>(this)->toggleImp();
}
bool get(void)
{
return static_cast<Derived*>(this)->getImp();
}
private:
//
// base implementations
//
void setImp()
{
std::cout << "base implementation of set()!" << std::endl;
}
void toggleImp()
{
std::cout << "base implementation of toggle()!" << std::endl;
}
bool getImp(void)
{
std::cout << "base implementation of get()!" << std::endl;
return true;
}
};
//
// implementations
//
struct STM32_Pin : PinBase<STM32_Pin>
{
STM32_Pin()
{
//std::cout << "created STM32_Pin" << std::endl;
}
void setImp(bool logic)
{
//std::cout << "stm32 pin set to " << logic << std::endl;
}
void toggleImp()
{
//std::cout << "toggled stm32 pin" << std::endl;
}
bool getImp()
{
return true;
}
void STM32_stuff()
{
//std::cout << "STM_32 specific stuff" << std::endl;
}
};
struct AVR_Pin : PinBase<AVR_Pin>
{
AVR_Pin()
{
a = 3;
//std::cout << "created AVR_Pin" << std::endl;
}
void setImp(bool logic)
{
//std::cout << "AVR pin set to " << logic << std::endl;
}
void toggleImp()
{
a = 5;
//std::cout << "toggled AVR pin" << std::endl;
}
bool getImp()
{
return true;
}
void avr_stuff()
{
a = 10;
//std::cout << "AVR specific stuff" << std::endl;
}
private:
int a;
};
template<typename T>
void foo(T& base)
{
base.set(true);
base.set(false);
base.toggle();
}
template<typename T>
void baa(PinBase<T>& pin)
{
pin.toggle();
//foo(pin);
}
#if 0
template <typename T>
struct Driver
{
Driver(PinBase<T>& pin) : pin(pin)
{
}
void doSomething()
{
pin.toggle();
}
private:
PinBase<T> pin;
};
#endif
struct Driver
{
Driver(IPin& pin) : pin(pin)
{
}
void doSomething()
{
pin.toggle();
}
private:
IPin& pin;
};
int main(void)
{
//STM32_Pin pin1;
AVR_Pin pin2;
//pin1.STM32_stuff();
pin2.avr_stuff();
#if 0
foo(pin1);
foo(pin2);
baa(pin1);
#endif
Driver drv(pin2);
drv.doSomething();
return 0;
}

@ -0,0 +1,5 @@
Curiously recurring template pattern (CRTP)
https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
https://www.youtube.com/watch?v=7-nHdQjSRe0&t=480s

@ -0,0 +1,29 @@
cpp_src = $(wildcard *.cpp)
cpp_src += $(wildcard ./utils/*.cpp)
cpp_src += $(wildcard ./driver/*.cpp)
cpp_obj = $(cpp_src:.cpp=.o)
c_obj = $(c_src:.c=.o)
CC = g++
CFLAGS = -Wall -pedantic -li2c
LDFLAGS = -lpthread
EXEC = runtest
all : $(EXEC)
$(EXEC): $(cpp_obj) $(c_obj)
$(CC) -o $@ $^ $(LDFLAGS)
debug : $(EXEC)
$(EXEC): $(cpp_obj) $(c_obj)
$(CC) -g -o $@ $^ $(LDFLAGS)
clean:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear
cleanall:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear

@ -0,0 +1,77 @@
#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
pthread_mutex_t print_mtx;
class IThread
{
public:
private:
virtual void* _run() = 0;
static void* _staticRun(void* context)
{
return static_cast<IThread*>(context)->_run();
}
};
void printer(std::string a)
{
pthread_mutex_lock(&print_mtx);
std::cout << a << std::endl;
pthread_mutex_unlock(&print_mtx);
}
void* foo(void* arg)
{
unsigned int i = 100;
for(;i > 0; i--){
std::string a = "foo cnt: ";
a += std::to_string(i);
printer(a);
sleep(1);
}
}
void* baa(void* arg)
{
unsigned int i = 5;
for(;i > 0; i--){
std::string a = "baa cnt: ";
a += std::to_string(i);
printer(a);
sleep(10);
}
}
int main()
{
pthread_t foo_th, baa_th;
pthread_mutex_init(&print_mtx, NULL);
pthread_create(&foo_th, NULL, foo, NULL);
pthread_create(&baa_th, NULL, baa, NULL);
pthread_join(foo_th, NULL);
pthread_join(baa_th, NULL);
return 0;
}

Binary file not shown.

@ -0,0 +1,47 @@
{
"files.associations": {
"array": "cpp",
"atomic": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"typeinfo": "cpp"
}
}

@ -0,0 +1,24 @@
cpp_src = $(wildcard *.cpp)
cpp_src += $(wildcard ./utils/*.cpp)
cpp_src += $(wildcard ./driver/*.cpp)
cpp_obj = $(cpp_src:.cpp=.o)
c_obj = $(c_src:.c=.o)
CC = g++
CFLAGS = -Wall -pedantic -li2c
LDFLAGS =
EXEC = runtest
all : $(EXEC)
$(EXEC): $(cpp_obj) $(c_obj)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear
cleanall:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear

@ -1,14 +1,69 @@
#include "device.hpp"
#include <iostream>
Device::Device()
Device::Device() :
reg_control(0x00)
{
Reg_Control.POWER_DEV = Reg_Control::POWER_DEV::TURN_OFF;
Reg_Control.SPEED = Reg_Control::SPEED::STAND_STILL;
std::cout << Reg_Control.raw;
std::cout << "Device::Device()" << std::endl;
std::cout << +reg_control.raw << std::endl;
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_OFF;
reg_control.bits.SPEED = Reg_Control::SPEED::STAND_STILL;
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
std::cout << "SPEED = " <<+reg_control.bits.SPEED << std::endl;
}
void Device::doSomething()
{
std::cout << "Device::doSomething()" << std::endl;
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
reg_control.bits.SPEED = Reg_Control::SPEED::FAST;
if(reg_control.bits.POWER_DEV == Reg_Control::POWER_DEV::TURN_ON){
std::cout << "device turned on!" << std::endl;
}
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
std::cout << +reg_control << std::endl;
reg_control = 0;
std::cout << +reg_control << std::endl;
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
//reg_control.bits.SPEED = Reg_Control::SPEED::FAST;
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
}
void Device::status()
{
// imitating read hardware register (for example reading from device via SPI or i2c)
reg_motorStatus = 0xFE;
if(reg_motorStatus.bits.POWER == Reg_MotorStatus::POWER::ON) {
std::cout << "Motor is Powered ON!" << std::endl;
} else {
std::cout << "Motor is Powered OFF!" << std::endl;
}
// will throw error because this bitfield is set const!
//reg_motorStatus.bits.STATUS = Reg_MotorStatus::STATUS::STANDSTILL;
std::cout << +reg_motorStatus.bits.POWER << std::endl;
std::cout << "Motor Status : " << +reg_motorStatus.bits.STATUS << std::endl;
}

@ -1,7 +1,7 @@
#ifndef _DEVICE_HPP_
#define _DEVICE_HPP_
#include"../BitField.hpp"
#include "../utils/BitField.hpp"
#include <iostream>
#include <stdint.h>
@ -13,6 +13,8 @@ class Device
void doSomething();
void status();
private:
//
@ -44,26 +46,68 @@ class Device
#endif
union Reg_Control
{
// bit 7
// bit 4
struct POWER_DEV{
typedef Bits<uint8_t, 7, 1> bits;
typedef BitField<uint8_t, 7, 1> Bits;
enum{TURN_OFF = 0, TURN_ON = 1};
};
// bits 2-3
struct SPEED{
typedef Bits<uint8_t, 2, 2> bits;
typedef BitField<uint8_t, 2, 2> Bits;
enum{STAND_STILL = 0,
SLOW = 1,
NORMAL = 2,
FAST = 3};
};
union Bits{
Reg_Control::POWER_DEV::bits POWER_DEV;
Reg_Control::SPEED::bits SPEED;
Reg_Control::POWER_DEV::Bits POWER_DEV;
Reg_Control::SPEED::Bits SPEED;
} bits;
// raw value. all bitfields will be "unified" here ;)
uint8_t raw;
// union Ctor with default value set to 0x00
Reg_Control(uint8_t v = 0x00) : raw(v) {}
// raw value extraction of register
operator uint8_t() {return raw;}
// used for updating software immage of hardware register
void operator = (uint8_t v) {raw = v;}
};
union Reg_MotorStatus
{
struct POWER{
typedef BitField<uint8_t,0,1> Bits;
enum{OFF = 0, ON = 1};
};
struct STATUS{
typedef BitField<uint8_t, 2,3>Bits;
enum{STANDSTILL = 0,
ACCELERATING_CW = 1,
DEACCELERATING_CW = 2,
ACCELERATING_CCW = 3,
DEACCELERATING_CCW = 4,
CONSTANT_SPEED = 5,
BLOCKED = 6};
};
union Bits
{
// is set const because it only used for status indication
const Reg_MotorStatus::POWER::Bits POWER;
const Reg_MotorStatus::STATUS::Bits STATUS;
}bits;
uint8_t raw;
Reg_MotorStatus(uint8_t v = 0x00) : raw(v) {}
operator uint8_t() {return raw;}
void operator = (uint8_t v) {raw = v;}
};
Reg_Control reg_control;
Reg_MotorStatus reg_motorStatus;
};
#endif // _DEVICE_HPP_

@ -1,9 +1,57 @@
#include <iostream>
#include <stdint.h>
#include "mcp4725/mcp4725.hpp"
#include "./driver/device.hpp"
#include "./utils/BitField.hpp"
#ifdef SIMPLE_TEST
int main(void)
{
std::cout << "test" << std::endl;
BitField<uint8_t, 1, 2> bitfield_0;
BitField<uint8_t, 5, 2> bitfield_1;
std::cout << "testing bitfield 0" << std::endl;
for(uint8_t i = 0; i < 10; i++) {
bitfield_0 = i;
std::cout << static_cast<uint32_t>(bitfield_0()) << std::endl;
}
std::cout << "testing bitfield 1" << std::endl;
for(uint8_t i = 0; i < 10; i++) {
bitfield_1 = i;
std::cout << static_cast<uint32_t>(bitfield_1()) << std::endl;
}
Device dev();
return 0;
}
#endif
int main(void)
{
std::cout << "test" << std::endl;
//std::cout << std::hex << ((1ULL << 2)-1) << std::endl;
std::cout << 1ULL << std::endl;
Device dev;
//dev.doSomething();
dev.status();
//dev.doSomething();
return 0;
}

@ -1,124 +0,0 @@
#include "mcp4725.hpp"
#if 0
MCP4725::MCP4725(pwrd_md power_down_mode,
i2c_addr address,
I2C* i2c) :
power_down_mode(power_down_mode),
address(address),
i2c(i2c),
dac_value(0),
eeprom_value(0)
{
uint8_t temp[6];
temp[0] = cmd_write_dac_and_eeprom | (power_down_mode << 1);
temp[1] = static_cast<uint8_t>(dac_value >> 4);
temp[2] = static_cast<uint8_t>(dac_value << 4);
temp[3] = temp[0];
temp[4] = temp[1];
temp[5] = temp[2];
//i2c_write(address, temp,6);
}
MCP4725::MCP4725(i2c_addr address,
I2C* i2c) :
power_down_mode(pwrd_md::normal),
address(address),
i2c(i2c),
dac_value(0),
eeprom_value(0)
{
uint8_t temp[6];
temp[0] = cmd_write_dac_and_eeprom | (power_down_mode << 1);
temp[1] = static_cast<uint8_t>(dac_value >> 4);
temp[2] = static_cast<uint8_t>(dac_value << 4);
temp[3] = temp[0];
temp[4] = temp[1];
temp[5] = temp[2];
//i2c_write(address, temp, 6);
}
#endif
MCP4725::MCP4725()
{
}
MCP4725::MCP4725(I2C* i2c) :
power_down_mode(pwrd_md::normal),
address(addr_0x60),
i2c(i2c),
dac_value(0),
eeprom_value(0)
{
uint8_t temp[6];
temp[0] = cmd_write_dac_and_eeprom | (power_down_mode << 1);
temp[1] = static_cast<uint8_t>(dac_value >> 4);
temp[2] = static_cast<uint8_t>(dac_value << 4);
temp[3] = temp[0];
temp[4] = temp[1];
temp[5] = temp[2];
i2c->writeBuffer(address, temp, 6);
}
//MCP4725::~MCP4725()
//{
//}
void MCP4725::operator=(uint16_t dac_value)
{
uint8_t temp[3];
this->dac_value = dac_value;
temp[0] = cmd_write_dac | (power_down_mode << 1);
temp[1] = static_cast<uint8_t>(dac_value >> 4);
temp[2] = static_cast<uint8_t>(dac_value << 4);
i2c->writeBuffer(address, temp, 3);
//i2c_write(address, temp, 3);
}
void MCP4725::operator==(uint16_t dac_and_eeprom_value)
{
uint8_t temp[6];
dac_value = dac_and_eeprom_value;
eeprom_value = dac_value;
temp[0] = cmd_write_dac_and_eeprom | (power_down_mode << 1);
temp[1] = static_cast<uint8_t>(dac_and_eeprom_value >> 4);
temp[2] = static_cast<uint8_t>(dac_and_eeprom_value << 4);
temp[3] = temp[0];
temp[4] = temp[1];
temp[5] = temp[2];
i2c->writeBuffer(address, temp, 6);
}
#if 0
void MCP4725::write_dac(uint16_t dac_value)
{
&this = dac_value;
}
void MCP4725::write_dac_and_eeprom(uint16_t dac_and_eeprom_value)
{
&this == dac_and_eeprom_value;
}
#endif

@ -1,100 +0,0 @@
#ifndef _MCP4725_HPP_
#define _MCP4725_HPP_
#include <stdint.h>
#include <unistd.h>
#include <functional>
#include "../../communication/i2c/i2c.hpp"
class MCP4725
{
public:
//typedef std::function<void(uint8_t,uint8_t*,uint8_t)> i2c_write_n_t;
//typedef std::function<void(const uint8_t&,const uint8_t*,const uint8_t&)> i2c_write_n_t;
//typedef void(*i2c_write_n_t)(const uint8_t&, const uint8_t*, const uint8_t&);
//typedef std::function<void(int)>i2c_write_n_t;
// address list
enum i2c_addr
{
addr_0x60 = 0b01100000,
addr_0x61 = addr_0x60 + 1,
addr_0x62 = addr_0x60 + 2,
addr_0x63 = addr_0x60 + 3,
addr_0x64 = addr_0x60 + 4,
addr_0x65 = addr_0x60 + 5,
addr_0x66 = addr_0x60 + 6,
addr_0x67 = addr_0x60 + 7
};
// power down impedance modes
enum pwrd_md
{
normal = 0x04,
ohm_1k = 0x01,
ohm_100k = 0x02,
ohm_500k = 0x03
};
//using std::functional<uint8_t(uint8_t, uint8_t)> i2c_read_n_t;
//using i2c_write_n_t = std::functional<void(uint8_t, uint8_t*,uint8_t)>;
/**
* @brief Constructor of mcp4725 dac
*
* @param power_down_mode pwrd_md power down mode
* @param address i2c_addr i2c address of the dac
* @param i2c_write i2c_write_n_t callback for i2c writ
*/
#if 0
MCP4725(pwrd_md power_down_mode,
i2c_addr address,
I2C* i2c);
MCP4725(i2c_addr address,
I2C* i2c);
#endif
MCP4725();
MCP4725(I2C* i2c);
// ~MCP4725();
void operator=(uint16_t dac_value);
void operator==(uint16_t dac_and_eeprom_value);
#if 0
void write_dac_and_eeprom(uint16_t value);
void set_powerdown_impedance(pwrd_md mode);
i2c_addr get_i2c_addr();
#endif
//void set_power
private:
enum commands_t
{
cmd_fast_mode = 0x00,
cmd_write_dac = 0x40,
cmd_write_dac_and_eeprom = 0x60
};
I2C* i2c;
i2c_addr address;
pwrd_md power_down_mode;
//i2c_write_n_t i2c_write;
uint16_t dac_value;
uint16_t eeprom_value;
};
#endif // _MCP4725_HPP_

@ -0,0 +1,126 @@
// Example program
#include <iostream>
#include <string>
#include <stdint.h>
/**
* @brief Template class for portable Bitfields
*
* @tparam T type of variable in which the bitfield resides
* @tparam START bit index starting from LSB where the bitfield starts
* @tparam SIZE number of bits
*/
template<typename T, uint8_t START, uint8_t SIZE>
struct BitField
{
/**
* @brief Construct a new Bit Field object
*
*/
BitField()
{
static_assert(SIZE != 0, "Bitfield SIZE must be > 0!");
static_assert(START < sizeof(T) * 8, "START exceeds number of bits of the chosen typename T!");
}
/**
* @brief assignment operator
*
* @param v value to be written in the bitfield
* @return BitField&
*/
BitField& operator =(T v)
{
#if 0
_raw = ((v & ((1ULL << SIZE)-1)) << START);
return *this;
#else
//_raw & ~(((1ULL << SIZE)-1) << START);
// use bit band alias if system permits
_raw = ((v & ((1ULL << SIZE)-1)) << START) | (_raw & ~(((1ULL << SIZE)-1) << START));
return *this;
//#endif
#endif
}
/**
* @brief return the value inside the bitfield
*
* @return T
*/
operator T() const
{
return _raw >> START;
}
/**
* @brief return the raw value
*
* @return T
*/
T operator ()() const
{
return _raw;
}
private:
T _raw;
};
union Reg_Control
{
// bit 4
struct POWER_DEV{
typedef BitField<uint8_t, 7, 1> Bits;
enum{TURN_OFF = 0, TURN_ON = 1};
};
// bits 2-3
struct SPEED{
typedef BitField<uint8_t, 0, 2> Bits;
enum{STAND_STILL = 0,
SLOW = 1,
NORMAL = 2,
FAST = 3};
};
union Bits{
Reg_Control::POWER_DEV::Bits POWER_DEV;
Reg_Control::SPEED::Bits SPEED;
} bits;
// raw value. all bitfields will be "unified" here ;)
uint8_t raw;
// union Ctor with default value set to 0x00
Reg_Control(uint8_t v = 0x00) : raw(v) {}
};
int main()
{
Reg_Control reg;
//reg.bits.SPEED = Reg_Control::SPEED::FAST;
reg.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
std::cout << +reg.raw << std::endl;
reg.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_OFF;
std::cout << +reg.raw << std::endl;
reg.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
reg.bits.SPEED = Reg_Control::SPEED::SLOW;
std::cout << +reg.raw << std::endl;
reg.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_OFF;
reg.bits.SPEED = Reg_Control::SPEED::FAST;
std::cout << +reg.raw << std::endl;
return 0;
}

@ -14,6 +14,9 @@
// https://stackoverflow.com/questions/31726191/is-there-a-portable-alternative-to-c-bitfields
// https://stackoverflow.com/questions/1392059/algorithm-to-generate-bit-mask
#ifndef _BITFIELDS_HPP_
#define _BITFIELDS_HPP_
#include <stdint.h>
/**
@ -44,8 +47,8 @@ struct BitField
*/
BitField& operator =(T v)
{
// mask creation for v : https://stackoverflow.com/questions/1392059/algorithm-to-generate-bit-mask
_raw = ((v & ((1ULL << SIZE)-1)) << START) ;
// use bit band alias if system permits
_raw = ((v & ((1ULL << SIZE)-1)) << START) | (_raw & ~(((1ULL << SIZE)-1) << START));
return *this;
}
@ -56,7 +59,7 @@ struct BitField
*/
operator T() const
{
return _raw >> START;
return (_raw >> START) & ((1ULL << SIZE) - 1);
}
/**
@ -66,9 +69,11 @@ struct BitField
*/
T operator ()() const
{
return _raw;
return (_raw >> START) & ((1ULL << SIZE) - 1);
}
private:
T _raw;
};
#endif // _BITFIELDS_HPP_

@ -0,0 +1,24 @@
cpp_src = $(wildcard *.cpp)
cpp_src += $(wildcard ./utils/*.cpp)
cpp_src += $(wildcard ./driver/*.cpp)
cpp_obj = $(cpp_src:.cpp=.o)
c_obj = $(c_src:.c=.o)
CC = g++
CFLAGS = -Wall -pedantic -li2c
LDFLAGS =
EXEC = runtest
all : $(EXEC)
$(EXEC): $(cpp_obj) $(c_obj)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear
cleanall:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear

@ -0,0 +1,105 @@
#include <iostream>
#include <stdint.h>
#include "utils/BitField.hpp"
union GPIO_MODER
{
struct MODER{
enum{
INPUT_MODE,
OUTPUT,
ALT_FUNCTION,
ANALOG
};
};
struct MODER_0 : public MODER{
typedef BitField<uint32_t, 0, 2> Bits;
};
struct MODER_1 : public MODER{
typedef BitField<uint32_t, 2, 2> Bits;
};
struct MODER_2 : public MODER{
typedef BitField<uint32_t, 4, 2> Bits;
};
struct MODER_3 : public MODER{
typedef BitField<uint32_t, 6, 2> Bits;
};
struct MODER_4 : public MODER{
typedef BitField<uint32_t, 8, 2> Bits;
};
struct MODER_5 : public MODER{
typedef BitField<uint32_t, 10, 2> Bits;
};
struct MODER_6 : public MODER{
typedef BitField<uint32_t, 12, 2> Bits;
};
struct MODER_7 : public MODER{
typedef BitField<uint32_t, 14, 2> Bits;
};
struct MODER_8 : public MODER{
typedef BitField<uint32_t, 16, 2> Bits;
};
struct MODER_9 : public MODER{
typedef BitField<uint32_t, 18, 2> Bits;
};
struct MODER_10 : public MODER{
typedef BitField<uint32_t, 20, 2> Bits;
};
struct MODER_11 : public MODER{
typedef BitField<uint32_t, 22, 2> Bits;
};
struct MODER_12 : public MODER{
typedef BitField<uint32_t, 24, 2> Bits;
};
struct MODER_13 : public MODER{
typedef BitField<uint32_t, 26, 2> Bits;
};
struct MODER_14 : public MODER{
typedef BitField<uint32_t, 28, 2> Bits;
};
struct MODER_15 : public MODER{
typedef BitField<uint32_t, 30, 2> Bits;
};
union{
GPIO_MODER::MODER_0::Bits MODER_0;
GPIO_MODER::MODER_1::Bits MODER_1;
GPIO_MODER::MODER_2::Bits MODER_2;
GPIO_MODER::MODER_3::Bits MODER_3;
GPIO_MODER::MODER_4::Bits MODER_4;
GPIO_MODER::MODER_5::Bits MODER_5;
GPIO_MODER::MODER_6::Bits MODER_6;
GPIO_MODER::MODER_7::Bits MODER_7;
GPIO_MODER::MODER_8::Bits MODER_8;
GPIO_MODER::MODER_9::Bits MODER_9;
GPIO_MODER::MODER_10::Bits MODER_10;
GPIO_MODER::MODER_11::Bits MODER_11;
GPIO_MODER::MODER_12::Bits MODER_12;
GPIO_MODER::MODER_13::Bits MODER_13;
GPIO_MODER::MODER_14::Bits MODER_14;
GPIO_MODER::MODER_15::Bits MODER_15;
}bits;
uint32_t raw;
GPIO_MODER(uint32_t v = 0x00) : raw(v) {}
operator uint32_t() {return raw;}
void operator = (uint32_t v) {raw = v;}
};
int main(void)
{
GPIO_MODER MODER_A;
// for reference use the STM32F0 reference manualchapter GPIO
MODER_A.bits.MODER_0 = GPIO_MODER::MODER_0::OUTPUT;
MODER_A.bits.MODER_5 = GPIO_MODER::MODER_5::ALT_FUNCTION;
std::cout << +MODER_A << std::endl;
return 0;
}

@ -0,0 +1,79 @@
/**
* @file BitField.h
* @author Edwin Koch (eddyed.k@gmail.com)
* @brief
* @version 0.1
* @date 2020-12-19
*
* @copyright Copyright (c) 2020
*
*/
// Based on:
// https://www.youtube.com/watch?v=TYqbgvHfxjM
// https://stackoverflow.com/questions/31726191/is-there-a-portable-alternative-to-c-bitfields
// https://stackoverflow.com/questions/1392059/algorithm-to-generate-bit-mask
#ifndef _BITFIELDS_HPP_
#define _BITFIELDS_HPP_
#include <stdint.h>
/**
* @brief Template class for portable Bitfields
*
* @tparam T type of variable in which the bitfield resides
* @tparam START bit index starting from LSB where the bitfield starts
* @tparam SIZE number of bits
*/
template<typename T, uint8_t START, uint8_t SIZE>
struct BitField
{
/**
* @brief Construct a new Bit Field object
*
*/
BitField()
{
static_assert(SIZE != 0, "Bitfield SIZE must be > 0!");
static_assert(START < sizeof(T) * 8, "START exceeds number of bits of the chosen typename T!");
}
/**
* @brief assignment operator
*
* @param v value to be written in the bitfield
* @return BitField&
*/
BitField& operator =(T v)
{
// use bit band alias if system permits
_raw = ((v & ((1ULL << SIZE)-1)) << START) | (_raw & ~(((1ULL << SIZE)-1) << START));
return *this;
}
/**
* @brief return the value inside the bitfield
*
* @return T
*/
operator T() const
{
return (_raw >> START) & ((1ULL << SIZE) - 1);
}
/**
* @brief return the raw value
*
* @return T
*/
T operator ()() const
{
return (_raw >> START) & ((1ULL << SIZE) - 1);
}
private:
T _raw;
};
#endif // _BITFIELDS_HPP_

@ -45,7 +45,8 @@ struct BitField
BitField& operator =(T v)
{
// mask creation for v : https://stackoverflow.com/questions/1392059/algorithm-to-generate-bit-mask
_raw = ((v & ((1ULL << SIZE)-1)) << START) ;
//_raw = ((v & ((1ULL << SIZE)-1)) << START) ;
_raw = ((v & ((1ULL << SIZE)-1)) << START) | (_raw & ~(((1ULL << SIZE)-1) << START));
return *this;
}
@ -56,7 +57,12 @@ struct BitField
*/
operator T() const
{
return _raw >> START;
//return 0;
return 0;
//return (_raw >> START) & ((1ULL << SIZE)-1);
//return (_raw >> START) & ((1ULL << SIZE)-1);
//return (_raw & (((1ULL << SIZE)-1) << START)) >> START;
}
/**
@ -66,7 +72,10 @@ struct BitField
*/
T operator ()() const
{
return _raw;
//return _raw;
return 0;
//return (_raw >> START) & ((1ULL << SIZE)-1);
}
private:

@ -0,0 +1,31 @@
//
// counter.c
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2019
//
#include "counter.h"
static int countValue;
void cnt_init(int val)
{
countValue = val;
}
void cnt_count(int step)
{
countValue += step;
}
int cnt_getCounter()
{
return countValue;
}
void cnt_setCounter(int val)
{
countValue = val;
}

@ -0,0 +1,24 @@
//
// counter.h
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2019
//
#ifndef COUNTER_H__
#define COUNTER_H__
void cnt_init(int val);
// initializes counter to val
void cnt_count(int step);
// counts the counter up (step>0) or down (step<0) by step
int cnt_getCounter();
// returns the counter value
void cnt_setCounter(int val);
// sets the counter to val
#endif

@ -0,0 +1,91 @@
//
// counterCtrl.c
//
// implements the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2019
//
#include <stdio.h>
#include "counterCtrl.h"
#include "counter.h"
typedef enum {idleState, // idle state
countUpState, // counting up at each count event
countDownState} // counting down at each count event
State;
static State currentState = idleState; // holds the current state of the FSM
void cnt_ctrlInit(int initValue)
{
currentState = idleState;
cnt_init(initValue);
}
void cnt_ctrlProcess(cnt_Event e)
{
switch (currentState)
{
case idleState:
printf("State: idleState\n");
if (cnt_evUp == e)
{
// actions
printf("State: idleState, counter = %d\n", cnt_getCounter());
// state transition
printf("Changing to State: countUpState\n");
currentState = countUpState;
}
else if (cnt_evDown == e)
{
// actions
printf("State: idleState, counter = %d\n", cnt_getCounter());
// state transition
printf("Changing to State: countDownState\n");
currentState = countDownState;
}
break;
case countUpState:
printf("State: countUpState\n");
if (cnt_evCount == e)
{
// actions
cnt_count(1);
printf("State: countUpState, counter = %d\n", cnt_getCounter());
// state transition
}
else if (cnt_evStop == e)
{
// actions
// state transition
printf("Changing to State: idleState\n");
currentState = idleState;
}
break;
case countDownState:
printf("State: countDownState\n");
if (cnt_evCount == e)
{
// actions
cnt_count(-1);
printf("State: countDownState, counter = %d\n", cnt_getCounter());
// state transition
}
else if (cnt_evStop == e)
{
// actions
// state transition
printf("Changing to State: idleState\n");
currentState = idleState;
}
break;
default:
break;
}
}

@ -0,0 +1,25 @@
//
// counterCtrl.h
//
// implements the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2019
//
#ifndef COUNTERCTRL_H__
#define COUNTERCTRL_H__
typedef enum {cnt_evUp, // count upwards
cnt_evDown, // count downwards
cnt_evCount, // count (up or down)
cnt_evStop} // stop counting
cnt_Event;
void cnt_ctrlInit(int initValue);
// initializes counter FSM
void cnt_ctrlProcess(cnt_Event e);
// changes the state of the FSM based on the event 'e'
// starts the actions
#endif

@ -0,0 +1,53 @@
//
// counterTest.c
//
// Test program for the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2019
//
#include <stdio.h>
#include "counterCtrl.h"
int main(void)
{
char answer;
cnt_ctrlInit(0);
do
{
printf("\n-------------------------------------------\n");
printf(" u Count up\n");
printf(" d Count down\n");
printf(" c Count\n");
printf(" s Stop counting\n");
printf(" q Quit\n");
printf("\nPlease press key: ");
scanf("%c", &answer);
getchar(); // nach scanf() ist noch ein '\n' im Inputbuffer: auslesen und wegwerfen
printf("\n");
switch (answer)
{
case 'u':
cnt_ctrlProcess(cnt_evUp);
break;
case 'd':
cnt_ctrlProcess(cnt_evDown);
break;
case 'c':
cnt_ctrlProcess(cnt_evCount);
break;
case 's':
cnt_ctrlProcess(cnt_evStop);
break;
default:
break;
}
} while (answer != 'q');
return 0;
}

@ -0,0 +1,53 @@
//
// counterTest.c
//
// Test program for the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2014
//
#include <stdio.h>
#include "counterCtrl.h"
int main(void)
{
char answer;
cntCtrlInit(0);
do
{
printf("\n-------------------------------------------\n");
printf(" u Count up\n");
printf(" d Count down\n");
printf(" c Count\n");
printf(" s Stop counting\n");
printf(" q Quit\n");
printf("\nPlease press key: ");
scanf("%c", &answer);
// getchar(); // nach scanf() ist noch ein '\n' im Inputbuffer: auslesen und wegwerfen
printf("\n");
switch (answer)
{
case 'u':
cntCtrlProcess(cntEvUp);
break;
case 'd':
cntCtrlProcess(cntEvDown);
break;
case 'c':
cntCtrlProcess(cntEvCount);
break;
case 's':
cntCtrlProcess(cntEvStop);
break;
default:
break;
}
} while (answer != 'q');
return 0;
}

@ -0,0 +1,29 @@
#
# Makefile fuer Counter-Programm
# File: makefile
# Reto Bonderer, 24.11.2010
#
CC = gcc
LINK = gcc
# '-pedantic' sorgt dafuer, dass gcc streng arbeitet
#CFLAGS = -c -pedantic
#LFLAGS = -pedantic
CFLAGS = -c -Wall
LFLAGS = -Wall
OBJS = counter.o counterCtrl.o counterTest.o
EXE = counterTest
$(EXE): $(OBJS)
$(LINK) $(LFLAGS) -o $(EXE) $(OBJS)
counterTest.o: counterTest.c counterCtrl.h
$(CC) $(CFLAGS) counterTest.c
counter.o: counter.c counter.h
$(CC) $(CFLAGS) counter.c
counterCtrl.o: counterCtrl.c counterCtrl.h counter.h
$(CC) $(CFLAGS) counterCtrl.c
clean:
rm -f $(EXE) $(OBJS)

@ -0,0 +1,28 @@
//
// Counter.cpp
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#include "Counter.h"
Counter::Counter(int val): countValue(val)
{
}
void Counter::count(int step)
{
countValue += step;
}
int Counter::getCounter() const
{
return countValue;
}
void Counter::setCounter(int val)
{
countValue = val;
}

@ -0,0 +1,29 @@
//
// Counter.h
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#ifndef COUNTER_H__
#define COUNTER_H__
class Counter
{
public:
Counter(int val = 0);
void count(int step);
// counts the counter up (step>0) or down (step<0) by step
int getCounter() const;
// returns the counter value
void setCounter(int val);
// sets the counter to val
private:
int countValue;
};
#endif

@ -0,0 +1,84 @@
//
// CounterCtrl.cpp
//
// implements the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#include <iostream>
#include "CounterCtrl.h"
#include "Counter.h"
using namespace std;
CounterCtrl::CounterCtrl(int initValue) :
currentState(idleState),
myCounter(initValue)
{
}
void CounterCtrl::process(Event e)
{
switch (currentState)
{
case idleState:
cout << "State: idleState" << endl;
if (evUp == e)
{
// actions
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
// state transition
cout << "Changing to State: countUpState" << endl;
currentState = countUpState;
}
else if (evDown == e)
{
// actions
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
// state transition
cout << "Changing to State: countDownState" << endl;
currentState = countDownState;
}
break;
case countUpState:
cout << "State: countUpState" << endl;
if (evCount == e)
{
// actions
myCounter.count(1);
cout << "State: countUpState, counter = " << myCounter.getCounter() << endl;
// state transition
}
else if (evStop == e)
{
// actions
// state transition
cout << "Changing to State: idleState" << endl;
currentState = idleState;
}
break;
case countDownState:
cout << "State: countDownState" << endl;
if (evCount == e)
{
// actions
myCounter.count(-1);
cout << "State: countDownState, counter = " << myCounter.getCounter() << endl;
// state transition
}
else if (evStop == e)
{
// actions
// state transition
cout << "Changing to State: idleState" << endl;
currentState = idleState;
}
break;
default:
break;
}
}

@ -0,0 +1,33 @@
//
// CounterCtrl.h
//
// implements the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#ifndef COUNTERCTRL_H__
#define COUNTERCTRL_H__
#include "Counter.h"
class CounterCtrl
{
public:
enum Event{evUp, // count upwards
evDown, // count downwards
evCount, // count (up or down)
evStop}; // stop counting
CounterCtrl(int initValue = 0);
void process(Event e);
// changes the state of the FSM based on the event 'e'
// starts the actions
private:
enum State{idleState, // idle state
countUpState, // counting up at each count event
countDownState}; // counting down at each count event
State currentState; // holds the current state of the FSM
Counter myCounter;
};
#endif

@ -0,0 +1,52 @@
//
// counterTest.cpp
//
// Test program for the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
//
#include <iostream>
#include "CounterCtrl.h"
using namespace std;
int main(void)
{
char answer;
CounterCtrl myFsm(0); // initValue of counter == 0
do
{
cout << endl << "-------------------------------------------" << endl;
cout << " u Count up" << endl;
cout << " d Count down" << endl;
cout << " c Count" << endl;
cout << " s Stop counting" << endl;
cout << " q Quit" << endl;
cout << endl << "Please press key: ";
cin >> answer;
cout << endl;
switch (answer)
{
case 'u':
myFsm.process(CounterCtrl::evUp);
break;
case 'd':
myFsm.process(CounterCtrl::evDown);
break;
case 'c':
myFsm.process(CounterCtrl::evCount);
break;
case 's':
myFsm.process(CounterCtrl::evStop);
break;
default:
break;
}
} while (answer != 'q');
return 0;
}

@ -0,0 +1,26 @@
#
# Makefile fuer Counter-Programm
# File: makefile
# Reto Bonderer, 23.10.2018
#
CC = g++
LINK = g++
CFLAGS = -c -Wall
LFLAGS = -Wall
OBJS = Counter.o CounterCtrl.o counterTest.o
EXE = counterTest
$(EXE): $(OBJS)
$(LINK) $(LFLAGS) -o $(EXE) $(OBJS)
counterTest.o: counterTest.cpp CounterCtrl.h
$(CC) $(CFLAGS) counterTest.cpp
Counter.o: Counter.cpp Counter.h
$(CC) $(CFLAGS) Counter.cpp
CounterCtrl.o: CounterCtrl.cpp CounterCtrl.h Counter.h
$(CC) $(CFLAGS) CounterCtrl.cpp
clean:
rm -f $(EXE) $(OBJS)

@ -0,0 +1,28 @@
//
// Counter.cpp
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#include "Counter.h"
Counter::Counter(int val): countValue(val)
{
}
void Counter::count(int step)
{
countValue += step;
}
int Counter::getCounter() const
{
return countValue;
}
void Counter::setCounter(int val)
{
countValue = val;
}

@ -0,0 +1,29 @@
//
// Counter.h
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#ifndef COUNTER_H__
#define COUNTER_H__
class Counter
{
public:
Counter(int val=0);
void count(int step);
// counts the counter up (step>0) or down (step<0) by step
int getCounter() const;
// returns the counter value
void setCounter(int val);
// sets the counter to val
private:
int countValue;
};
#endif

@ -0,0 +1,22 @@
//
// CounterCtrl.cpp
//
// implements the Finite State Machine (FSM) of an up/down-Counter
// CounterCtrl is the Context class in the State pattern
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
//
#include "CounterCtrl.h"
#include "CounterState.h"
CounterCtrl::CounterCtrl(int initValue):
entity(initValue),
pState(IdleState::getInstance()) // initial state
{
}
void CounterCtrl::process(Event e)
{ // delegates all requests to CounterState
pState = pState->handle(entity, e);
}

@ -0,0 +1,31 @@
//
// CounterCtrl.h
//
// implements the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
//
#ifndef COUNTERCTRL_H__
#define COUNTERCTRL_H__
#include "Counter.h"
class CounterState; // forward declaration
class CounterCtrl
// this is the 'Context' class of the State pattern
{
public:
enum Event{evUp, // count upwards
evDown, // count downwards
evCount, // count (up or down)
evStop}; // stop counting
CounterCtrl(int initValue = 0);
void process(Event e);
// changes the state of the FSM based on the event 'e'
private:
Counter entity;
CounterState* pState; // holds the current state
};
#endif

@ -0,0 +1,102 @@
//
// CounterState.cpp
//
// implements all states of an up/down-Counter
// this file contains all classes of the state machine.
// it may make sense to have separate files for each state
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
//
#include <iostream>
#include "CounterState.h"
using namespace std;
// class CounterState
CounterState* CounterState::changeState(Counter& entity, CounterState* pnewState)
{
return pnewState;
}
// class IdleState
IdleState IdleState::instance;
IdleState* IdleState::getInstance()
{
return &instance;
}
CounterState* IdleState::handle(Counter& entity, CounterCtrl::Event e)
{
cout << "State: idleState" << endl;
if (CounterCtrl::evUp == e)
{
// transition actions
cout << "counter = " << entity.getCounter() << endl;
// state transition
return changeState(entity, CountUpState::getInstance());
}
else if (CounterCtrl::evDown == e)
{
// transition actions
cout << "counter = " << entity.getCounter() << endl;
// state transition
return changeState(entity, CountDownState::getInstance());
}
return this;
}
// class CountUpState
CountUpState CountUpState::instance;
CountUpState* CountUpState::getInstance()
{
return &instance;
}
CounterState* CountUpState::handle(Counter& entity, CounterCtrl::Event e)
{
cout << "State: countUpState" << endl;
if (CounterCtrl::evCount == e)
{
// transition actions
entity.count(1);
cout << "counter = " << entity.getCounter() << endl;
// state transition
return changeState(entity, CountUpState::getInstance());
}
else if (CounterCtrl::evStop == e)
{
// transition actions
// state transition
return changeState(entity, IdleState::getInstance());
}
return this;
}
// class CountDownState
CountDownState CountDownState::instance;
CountDownState* CountDownState::getInstance()
{
return &instance;
}
CounterState* CountDownState::handle(Counter& entity, CounterCtrl::Event e)
{
cout << "State: countDownState" << endl;
if (CounterCtrl::evCount == e)
{
// transition actions
entity.count(-1);
cout << "counter = " << entity.getCounter() << endl;
// state transition
return changeState(entity, CountDownState::getInstance());
}
else if (CounterCtrl::evStop == e)
{
// transition actions
// state transition
return changeState(entity, IdleState::getInstance());
}
return this;
}

@ -0,0 +1,53 @@
//
// CounterState.h
//
// implements an up/down-Counter
// this file contains all classes of the state machine
// it may make sense to have separate files for each state
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, 21.10.2017
//
#ifndef COUNTERSTATE_H__
#define COUNTERSTATE_H__
#include "CounterCtrl.h" // Events are defined here
class CounterState // abstract base class
{
public:
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e) = 0;
// returns new state
protected: // only inherited classes may use these member functions
CounterState* changeState(Counter& entity, CounterState* pnewState);
};
class IdleState : public CounterState // it's a singleton
{
public:
static IdleState* getInstance();
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
private:
IdleState() {};
static IdleState instance;
};
class CountUpState : public CounterState // it's a singleton
{
public:
static CountUpState* getInstance();
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
private:
CountUpState() {};
static CountUpState instance;
};
class CountDownState : public CounterState // it's a singleton
{
public:
static CountDownState* getInstance();
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
private:
CountDownState() {};
static CountDownState instance;
};
#endif

@ -0,0 +1,52 @@
//
// counterTest.cpp
//
// Test program for the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#include <iostream>
#include "CounterCtrl.h"
using namespace std;
int main(void)
{
char answer;
CounterCtrl myFsm;
do
{
cout << endl << "-------------------------------------------" << endl;
cout << " u Count up" << endl;
cout << " d Count down" << endl;
cout << " c Count" << endl;
cout << " s Stop counting" << endl;
cout << " q Quit" << endl;
cout << endl << "Please press key: ";
cin >> answer;
cout << endl;
switch (answer)
{
case 'u':
myFsm.process(CounterCtrl::evUp);
break;
case 'd':
myFsm.process(CounterCtrl::evDown);
break;
case 'c':
myFsm.process(CounterCtrl::evCount);
break;
case 's':
myFsm.process(CounterCtrl::evStop);
break;
default:
break;
}
} while (answer != 'q');
return 0;
}

@ -0,0 +1,29 @@
#
# Makefile fuer Counter-Programm
# File: makefile
# Reto Bonderer, 21.10.2017
#
CC = g++
LINK = g++
# '-pedantic' sorgt dafuer, dass gcc streng arbeitet
CFLAGS = -c -pedantic -Wall
LFLAGS = -pedantic
OBJS = Counter.o CounterCtrl.o CounterState.o counterTest.o
counterTest: $(OBJS)
$(LINK) $(LFLAGS) -o counterTest $(OBJS)
counterTest.o: counterTest.cpp CounterCtrl.h
$(CC) $(CFLAGS) counterTest.cpp
Counter.o: Counter.cpp Counter.h
$(CC) $(CFLAGS) Counter.cpp
CounterCtrl.o: CounterCtrl.cpp CounterCtrl.h CounterState.h
$(CC) $(CFLAGS) CounterCtrl.cpp
CounterState.o: CounterState.cpp CounterState.h Counter.h CounterCtrl.h
$(CC) $(CFLAGS) CounterState.cpp
clean:
rm -f counterTest $(OBJS)

@ -0,0 +1,6 @@
{
"files.associations": {
"xmemory": "cpp",
"xstring": "cpp"
}
}

@ -0,0 +1,28 @@
//
// Counter.cpp
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
//
#include "Counter.h"
Counter::Counter(int val): countValue(val)
{
}
void Counter::count(int step)
{
countValue += step;
}
int Counter::getCounter() const
{
return countValue;
}
void Counter::setCounter(int val)
{
countValue = val;
}

@ -0,0 +1,29 @@
//
// Counter.h
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
//
#ifndef COUNTER_H__
#define COUNTER_H__
class Counter
{
public:
Counter(int val=0);
void count(int step);
// counts the counter up (step>0) or down (step<0) by step
int getCounter() const;
// returns the counter value
void setCounter(int val);
// sets the counter to val
private:
int countValue;
};
#endif

@ -0,0 +1,23 @@
//
// CounterCtrl.cpp
//
// implements the Finite State Machine (FSM) of an up/down-Counter
// CounterCtrl is the Context class in the State pattern
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2018
//
#include "Counter.h"
#include "CounterState.h"
#include "CounterCtrl.h"
CounterCtrl::CounterCtrl(int initValue) :
entity(initValue),
pState(CounterState::init(entity)) // initial state
{
}
void CounterCtrl::process(Event e)
{ // delegates all requests to CounterState
pState = pState->handle(entity, e); // entity: reference to entity class object
}

@ -0,0 +1,30 @@
//
// CounterCtrl.h
//
// implements the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
//
#ifndef COUNTERCTRL_H__
#define COUNTERCTRL_H__
#include "Counter.h"
class CounterState; // forward declaration
class CounterCtrl
// this is the 'Context' class of the State pattern
{
public:
enum Event{evUp, // count upwards
evDown, // count downwards
evCount, // count (up or down)
evStop}; // stop counting
CounterCtrl(int initValue = 0);
void process(Event e);
// changes the state of the FSM based on the event 'e'
private:
Counter entity; // entity class
CounterState* pState; // holds the current state
};
#endif

@ -0,0 +1,150 @@
//
// CounterState.cpp
//
// implements all states of an up/down-Counter
// this file contains all classes of the state machine.
// it may make sense to have separate files for each state
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2018
//
#include <iostream>
#include "CounterState.h"
using namespace std;
//class CounterState
CounterState* CounterState::init(Counter& entity) // is static
{
CounterState* initState = IdleState::getInstance();
initState->entryAction(entity); // executes entry action into init state
return initState;
}
CounterState* CounterState::changeState(Counter& entity,
Action ptransAction,
CounterState* pnewState)
{
exitAction(entity); // polymorphic call of exit action
(this->*ptransAction)(entity); // call of transition action
pnewState->entryAction(entity); // polymorphic call of entry action
return pnewState;
}
void CounterState::showCounter(Counter& entity)
{
cout << "counter = " << entity.getCounter() << endl;
}
void CounterState::countUp(Counter& entity)
{
entity.count(1);
cout << "counter = " << entity.getCounter() << endl;
}
void CounterState::countDown(Counter& entity)
{
entity.count(-1);
cout << "counter = " << entity.getCounter() << endl;
}
// class IdleState
IdleState IdleState::instance;
IdleState* IdleState::getInstance()
{
return &instance;
}
CounterState* IdleState::handle(Counter& entity, CounterCtrl::Event e)
{
cout << "State: idleState" << endl;
if (CounterCtrl::evUp == e)
{
// state transition
return changeState(entity, &IdleState::showCounter, CountUpState::getInstance());
}
else if (CounterCtrl::evDown == e)
{
// state transition
return changeState(entity, &IdleState::showCounter, CountDownState::getInstance());
}
return this;
}
void IdleState::entryAction(Counter& entity)
{
cout << "Entering idleState" << endl;
}
void IdleState::exitAction(Counter& entity)
{
cout << "Exiting from idleState" << endl;
}
// class CountUpState
CountUpState CountUpState::instance;
CountUpState* CountUpState::getInstance()
{
return &instance;
}
CounterState* CountUpState::handle(Counter& entity, CounterCtrl::Event e)
{
cout << "State: countUpState" << endl;
if (CounterCtrl::evCount == e)
{
// state transition
return changeState(entity, &CountUpState::countUp, CountUpState::getInstance());
}
else if (CounterCtrl::evStop == e)
{
// state transition
return changeState(entity, &CountUpState::emptyAction, IdleState::getInstance());
}
return this;
}
void CountUpState::entryAction(Counter& entity)
{
cout << "Entering countUpState" << endl;
}
void CountUpState::exitAction(Counter& entity)
{
cout << "Exiting from countUpState" << endl;
}
// class CountDownState
CountDownState CountDownState::instance;
CountDownState* CountDownState::getInstance()
{
return &instance;
}
CounterState* CountDownState::handle(Counter& entity, CounterCtrl::Event e)
{
cout << "State: countDownState" << endl;
if (CounterCtrl::evCount == e)
{
// state transition
return changeState(entity, &CountDownState::countDown, CountDownState::getInstance());
}
else if (CounterCtrl::evStop == e)
{
// state transition
return changeState(entity, &CountDownState::emptyAction, IdleState::getInstance());
}
return this;
}
void CountDownState::entryAction(Counter& entity)
{
cout << "Entering countDownState" << endl;
}
void CountDownState::exitAction(Counter& entity)
{
cout << "Exiting from countDownState" << endl;
}

@ -0,0 +1,73 @@
//
// CounterState.h
//
// implements an up/down-Counter
// this file contains all classes of the state machine
// it may make sense to have separate files for each state
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2018
//
#ifndef COUNTERSTATE_H__
#define COUNTERSTATE_H__
#include "CounterCtrl.h"
class CounterState // abstract base class
{
public:
static CounterState* init(Counter& entity);
// should be called first, returns new state
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e) = 0;
// returns new state
protected:
virtual void entryAction(Counter& entity) {};
virtual void exitAction(Counter& entity) {};
typedef void (CounterState::*Action)(Counter& entity); // ptr to action function
CounterState* changeState(Counter& entity, Action ptransAction, CounterState* pnewState);
// transition actions
void emptyAction(Counter& entity) {};
void showCounter(Counter& entity);
void countUp(Counter& entity);
void countDown(Counter& entity);
};
class IdleState : public CounterState // it's a singleton
{
public:
static IdleState* getInstance();
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
protected:
virtual void entryAction(Counter& entity);
virtual void exitAction(Counter& entity);
private:
IdleState() {};
static IdleState instance;
};
class CountUpState : public CounterState // it's a singleton
{
public:
static CountUpState* getInstance();
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
protected:
virtual void entryAction(Counter& entity);
virtual void exitAction(Counter& entity);
private:
CountUpState() {};
static CountUpState instance;
};
class CountDownState : public CounterState // it's a singleton
{
public:
static CountDownState* getInstance();
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
protected:
virtual void entryAction(Counter& entity);
virtual void exitAction(Counter& entity);
private:
CountDownState() {};
static CountDownState instance;
};
#endif

@ -0,0 +1,52 @@
//
// counterTest.cpp
//
// Test program for the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Nov. 2017
//
#include <iostream>
#include "CounterCtrl.h"
using namespace std;
int main(void)
{
char answer;
CounterCtrl myFsm;
do
{
cout << endl << "-------------------------------------------" << endl;
cout << " u Count up" << endl;
cout << " d Count down" << endl;
cout << " c Count" << endl;
cout << " s Stop counting" << endl;
cout << " q Quit" << endl;
cout << endl << "Please press key: ";
cin >> answer;
cout << endl;
switch (answer)
{
case 'u':
myFsm.process(CounterCtrl::evUp);
break;
case 'd':
myFsm.process(CounterCtrl::evDown);
break;
case 'c':
myFsm.process(CounterCtrl::evCount);
break;
case 's':
myFsm.process(CounterCtrl::evStop);
break;
default:
break;
}
} while (answer != 'q');
return 0;
}

@ -0,0 +1,30 @@
#
# Makefile fuer Counter-Programm
# File: makefile
# Reto Bonderer, 21.10.2017
#
CC = g++
LINK = g++
# '-pedantic' sorgt dafuer, dass g++ streng arbeitet
CFLAGS = -c -pedantic -Wall
LFLAGS = -pedantic
OBJS = Counter.o CounterCtrl.o CounterState.o counterTest.o
EXE = counterTest
$(EXE): $(OBJS)
$(LINK) $(LFLAGS) -o $(EXE) $(OBJS)
counterTest.o: counterTest.cpp CounterCtrl.h
$(CC) $(CFLAGS) counterTest.cpp
Counter.o: Counter.cpp Counter.h
$(CC) $(CFLAGS) Counter.cpp
CounterCtrl.o: CounterCtrl.cpp CounterCtrl.h CounterState.h
$(CC) $(CFLAGS) CounterCtrl.cpp
CounterState.o: CounterState.cpp CounterState.h Counter.h
$(CC) $(CFLAGS) CounterState.cpp
clean:
rm -f $(EXE) $(OBJS)

@ -0,0 +1,28 @@
//
// Counter.cpp
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#include "Counter.h"
Counter::Counter(int val): countValue(val)
{
}
void Counter::count(int step)
{
countValue += step;
}
int Counter::getCounter() const
{
return countValue;
}
void Counter::setCounter(int val)
{
countValue = val;
}

@ -0,0 +1,29 @@
//
// Counter.h
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#ifndef COUNTER_H__
#define COUNTER_H__
class Counter
{
public:
Counter(int val);
void count(int step);
// counts the counter up (step>0) or down (step<0) by step
int getCounter() const;
// returns the counter value
void setCounter(int val);
// sets the counter to val
private:
int countValue;
};
#endif

@ -0,0 +1,104 @@
//
// CounterCtrl.cpp
//
// implements the Finite State Machine (FSM) of an up/down-Counter as a table
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#include <iostream>
#include "CounterCtrl.h"
#include "Counter.h"
using namespace std;
const CounterCtrl::Transition CounterCtrl::fsm[] = // this table defines the fsm
{//currentState checker function action function next state
{idleState, &CounterCtrl::checkIdleUp, &CounterCtrl::actionIdleUp, countUpState},
{idleState, &CounterCtrl::checkIdleDown, &CounterCtrl::actionIdleDown, countDownState},
{countUpState, &CounterCtrl::checkUpUp, &CounterCtrl::actionUpUp, countUpState},
{countUpState, &CounterCtrl::checkUpIdle, &CounterCtrl::actionUpIdle, idleState},
{countDownState, &CounterCtrl::checkDownDown, &CounterCtrl::actionDownDown, countDownState},
{countDownState, &CounterCtrl::checkDownIdle, &CounterCtrl::actionDownIdle, idleState}
};
CounterCtrl::CounterCtrl(int initValue) :
currentState(idleState),
myCounter(initValue)
{
}
void CounterCtrl::process(Event e) // this function never changes
{
for (size_t i = 0; i < sizeof(fsm) / sizeof(Transition); ++i) // let compiler determine number of transitions
{
if (fsm[i].currentState == currentState && // is there an entry in the table?
(this->*fsm[i].pChecker)(e))
{
(this->*fsm[i].pAction)();
currentState = fsm[i].nextState;
break;
}
}
}
// check functions
bool CounterCtrl::checkIdleUp(Event e)
{
return evUp == e;
}
bool CounterCtrl::checkIdleDown(Event e)
{
return evDown == e;
}
bool CounterCtrl::checkUpIdle(Event e)
{
return evStop == e;
}
bool CounterCtrl::checkDownIdle(Event e)
{
return evStop == e;
}
bool CounterCtrl::checkUpUp(Event e)
{
return evCount == e;
}
bool CounterCtrl::checkDownDown(Event e)
{
return evCount == e;
}
// action functions
void CounterCtrl::actionIdleUp(void)
{
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
}
void CounterCtrl::actionIdleDown(void)
{
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
}
void CounterCtrl::actionUpIdle(void)
{
}
void CounterCtrl::actionDownIdle(void)
{
}
void CounterCtrl::actionUpUp(void)
{
myCounter.count(1);
cout << "State: countUpState, counter = " << myCounter.getCounter() << endl;
}
void CounterCtrl::actionDownDown(void)
{
myCounter.count(-1);
cout << "State: countDownState, counter = " << myCounter.getCounter() << endl;
}

@ -0,0 +1,60 @@
//
// CounterCtrl.h
//
// implements the Finite State Machine (FSM) of an up/down-Counter as a table
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#ifndef COUNTERCTRL_H__
#define COUNTERCTRL_H__
#include "Counter.h"
class CounterCtrl
{
public:
enum Event{evUp, // count upwards
evDown, // count downwards
evCount, // count (up or down)
evStop}; // stop counting
CounterCtrl(int initValue = 0);
void process(Event e);
// changes the state of the FSM based on the event 'e'
// starts the actions
private:
enum State{idleState, // idle state
countUpState, // counting up at each count event
countDownState}; // counting down at each count event
State currentState; // holds the current state of the FSM
Counter myCounter;
typedef bool (CounterCtrl::*Checker)(Event); // function ptr for checker function
typedef void (CounterCtrl::*Action)(void); // function ptr for action function
// check functions
bool checkIdleUp(Event e);
bool checkIdleDown(Event e);
bool checkUpIdle(Event e);
bool checkDownIdle(Event e);
bool checkUpUp(Event e);
bool checkDownDown(Event e);
// action functions
void actionIdleUp(void);
void actionIdleDown(void);
void actionUpIdle(void);
void actionDownIdle(void);
void actionUpUp(void);
void actionDownDown(void);
struct Transition
{
State currentState; // current state
Checker pChecker; // pointer to checker function
Action pAction; // pointer to action function
State nextState; // next state
};
static const Transition fsm[];
};
#endif

@ -0,0 +1,52 @@
//
// counterTest.cpp
//
// Test program for the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#include <iostream>
#include "CounterCtrl.h"
using namespace std;
int main(void)
{
char answer;
CounterCtrl myFsm(0);
do
{
cout << endl << "-------------------------------------------" << endl;
cout << " u Count up" << endl;
cout << " d Count down" << endl;
cout << " c Count" << endl;
cout << " s Stop counting" << endl;
cout << " q Quit" << endl;
cout << endl << "Please press key: ";
cin >> answer;
cout << endl;
switch (answer)
{
case 'u':
myFsm.process(CounterCtrl::evUp);
break;
case 'd':
myFsm.process(CounterCtrl::evDown);
break;
case 'c':
myFsm.process(CounterCtrl::evCount);
break;
case 's':
myFsm.process(CounterCtrl::evStop);
break;
default:
break;
}
} while (answer != 'q');
return 0;
}

@ -0,0 +1,26 @@
#
# Makefile fuer Counter-Programm
# File: makefile
# Reto Bonderer, 07.10.2017
#
CC = g++
LINK = g++
CFLAGS = -c -Wall
LFLAGS = -Wall
OBJS = Counter.o CounterCtrl.o counterTest.o
EXE = counterTest
$(EXE): $(OBJS)
$(LINK) $(LFLAGS) -o $(EXE) $(OBJS)
counterTest.o: counterTest.cpp CounterCtrl.h
$(CC) $(CFLAGS) counterTest.cpp
Counter.o: Counter.cpp Counter.h
$(CC) $(CFLAGS) Counter.cpp
CounterCtrl.o: CounterCtrl.cpp CounterCtrl.h Counter.h
$(CC) $(CFLAGS) CounterCtrl.cpp
clean:
rm -f $(EXE) $(OBJS)

@ -0,0 +1,28 @@
//
// Counter.cpp
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#include "Counter.h"
Counter::Counter(int val): countValue(val)
{
}
void Counter::count(int step)
{
countValue += step;
}
int Counter::getCounter() const
{
return countValue;
}
void Counter::setCounter(int val)
{
countValue = val;
}

@ -0,0 +1,29 @@
//
// Counter.h
//
// implements an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#ifndef COUNTER_H__
#define COUNTER_H__
class Counter
{
public:
Counter(int val);
void count(int step);
// counts the counter up (step>0) or down (step<0) by step
int getCounter() const;
// returns the counter value
void setCounter(int val);
// sets the counter to val
private:
int countValue;
};
#endif

@ -0,0 +1,69 @@
//
// CounterCtrl.cpp
//
// implements the Finite State Machine (FSM) of an up/down-Counter as a simple table
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#include <iostream>
#include "CounterCtrl.h"
#include "Counter.h"
using namespace std;
const CounterCtrl::Transition CounterCtrl::fsm[] = // this table defines the fsm
{//currentState triggering event action function next state
{idleState, evUp, &CounterCtrl::actionIdleUp, countUpState},
{idleState, evDown, &CounterCtrl::actionIdleDown, countDownState},
{countUpState, evCount, &CounterCtrl::actionUpUp, countUpState},
{countUpState, evStop, &CounterCtrl::actionDoNothing, idleState},
{countDownState, evCount, &CounterCtrl::actionDownDown, countDownState},
{countDownState, evStop, &CounterCtrl::actionDoNothing, idleState}
};
CounterCtrl::CounterCtrl(int initValue) :
currentState(idleState),
myCounter(initValue)
{
}
void CounterCtrl::process(Event e) // execution engine, this function never changes
{
for (size_t i = 0; i < sizeof(fsm) / sizeof(Transition); ++i) // determine number of transitions automatically
{
if (fsm[i].currentState == currentState && fsm[i].ev == e) // is there an entry in the table?
{
(this->*fsm[i].pAction)();
currentState = fsm[i].nextState;
break;
}
}
}
// action functions
void CounterCtrl::actionIdleUp(void)
{
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
}
void CounterCtrl::actionIdleDown(void)
{
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
}
void CounterCtrl::actionDoNothing(void)
{
}
void CounterCtrl::actionUpUp(void)
{
myCounter.count(1);
cout << "State: countUpState, counter = " << myCounter.getCounter() << endl;
}
void CounterCtrl::actionDownDown(void)
{
myCounter.count(-1);
cout << "State: countDownState, counter = " << myCounter.getCounter() << endl;
}

@ -0,0 +1,51 @@
//
// CounterCtrl.h
//
// implements the Finite State Machine (FSM) of an up/down-Counter as a simple table
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#ifndef COUNTERCTRL_H__
#define COUNTERCTRL_H__
#include "Counter.h"
class CounterCtrl
{
public:
enum Event{evUp, // count upwards
evDown, // count downwards
evCount, // count (up or down)
evStop}; // stop counting
CounterCtrl(int initValue = 0);
void process(Event e);
// changes the state of the FSM based on the event 'e'
// starts the actions
private:
enum State{idleState, // idle state
countUpState, // counting up at each count event
countDownState}; // counting down at each count event
State currentState; // holds the current state of the FSM
Counter myCounter;
typedef void (CounterCtrl::*Action)(void); // function ptr for action function
// action functions
void actionIdleUp(void);
void actionIdleDown(void);
void actionDoNothing(void);
void actionUpUp(void);
void actionDownDown(void);
struct Transition
{
State currentState; // current state
Event ev; // event triggering the transition
Action pAction; // pointer to action function
State nextState; // next state
};
static const Transition fsm[];
};
#endif

@ -0,0 +1,52 @@
//
// counterTest.cpp
//
// Test program for the Finite State Machine (FSM) of an up/down-Counter
//
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
//
#include <iostream>
#include "CounterCtrl.h"
using namespace std;
int main(void)
{
char answer;
CounterCtrl myFsm;
do
{
cout << endl << "-------------------------------------------" << endl;
cout << " u Count up" << endl;
cout << " d Count down" << endl;
cout << " c Count" << endl;
cout << " s Stop counting" << endl;
cout << " q Quit" << endl;
cout << endl << "Please press key: ";
cin >> answer;
cout << endl;
switch (answer)
{
case 'u':
myFsm.process(CounterCtrl::evUp);
break;
case 'd':
myFsm.process(CounterCtrl::evDown);
break;
case 'c':
myFsm.process(CounterCtrl::evCount);
break;
case 's':
myFsm.process(CounterCtrl::evStop);
break;
default:
break;
}
} while (answer != 'q');
return 0;
}

@ -0,0 +1,26 @@
#
# Makefile fuer Counter-Programm
# File: makefile
# Reto Bonderer, 07.10.2017
#
CC = g++
LINK = g++
CFLAGS = -c -Wall
LFLAGS = -Wall
OBJS = Counter.o CounterCtrl.o counterTest.o
EXE = counterTest
$(EXE): $(OBJS)
$(LINK) $(LFLAGS) -o $(EXE) $(OBJS)
counterTest.o: counterTest.cpp CounterCtrl.h
$(CC) $(CFLAGS) counterTest.cpp
Counter.o: Counter.cpp Counter.h
$(CC) $(CFLAGS) Counter.cpp
CounterCtrl.o: CounterCtrl.cpp CounterCtrl.h Counter.h
$(CC) $(CFLAGS) CounterCtrl.cpp
clean:
rm -f $(EXE) $(OBJS)

@ -0,0 +1,194 @@
/*****************************************************************************/
/* STDINT.H v5.2.1 */
/* Copyright (c) 2002-2009 Texas Instruments Incorporated */
/*****************************************************************************/
#ifndef _STDINT_H_
#define _STDINT_H_
/* 7.18.1.1 Exact-width integer types */
typedef int int16_t;
typedef unsigned int uint16_t;
typedef long int32_t;
typedef unsigned long uint32_t;
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
typedef long long int64_t;
typedef unsigned long long uint64_t;
#endif
/* 7.18.1.2 Minimum-width integer types */
typedef int16_t int_least8_t;
typedef uint16_t uint_least8_t;
typedef int16_t int_least16_t;
typedef uint16_t uint_least16_t;
typedef int32_t int_least32_t;
typedef uint32_t uint_least32_t;
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
typedef int64_t int_least64_t;
typedef uint64_t uint_least64_t;
#else
/* sorry, int_least64_t not implemented for C54x, C55x, MSP430 */
#endif
/* 7.18.1.3 Fastest minimum-width integer types */
typedef int16_t int_fast8_t;
typedef uint16_t uint_fast8_t;
typedef int16_t int_fast16_t;
typedef uint16_t uint_fast16_t;
typedef int32_t int_fast32_t;
typedef uint32_t uint_fast32_t;
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
typedef int64_t int_fast64_t;
typedef uint64_t uint_fast64_t;
#endif
/* 7.18.1.4 Integer types capable of holding object pointers */
typedef long intptr_t;
typedef unsigned long uintptr_t;
/* 7.18.1.5 Greatest-width integer types */
#if defined(__TMS320C55X__) || defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
typedef long long intmax_t;
typedef unsigned long long uintmax_t;
#elif defined(_TMS320C5XX) || defined(__TMS320C27X__) || defined(__MSP430__)
typedef long intmax_t;
typedef unsigned long uintmax_t;
#endif
/*
According to footnotes in the 1999 C standard, "C++ implementations
should define these macros only when __STDC_LIMIT_MACROS is defined
before <stdint.h> is included."
*/
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
/* 7.18.2 Limits of specified width integer types */
#define INT16_MAX 0x7fff
#define INT16_MIN (-INT16_MAX-1)
#define UINT16_MAX 0xffff
#define INT32_MAX 0x7fffffff
#define INT32_MIN (-INT32_MAX-1)
#define UINT32_MAX 0xffffffff
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
#define INT64_MAX 0x7fffffffffffffff
#define INT64_MIN (-INT64_MAX-1)
#define UINT64_MAX 0xffffffffffffffff
#endif
#define INT_LEAST8_MAX INT16_MAX
#define INT_LEAST8_MIN INT16_MIN
#define UINT_LEAST8_MAX UINT16_MAX
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST16_MIN INT16_MIN
#define UINT_LEAST16_MAX UINT16_MAX
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST32_MIN INT32_MIN
#define UINT_LEAST32_MAX UINT32_MAX
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
#define INT_LEAST64_MAX INT64_MAX
#define INT_LEAST64_MIN INT64_MIN
#define UINT_LEAST64_MAX UINT64_MAX
#endif
#define INT_FAST8_MAX INT16_MAX
#define INT_FAST8_MIN INT16_MIN
#define UINT_FAST8_MAX UINT16_MAX
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST16_MIN INT16_MIN
#define UINT_FAST16_MAX UINT16_MAX
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST32_MIN INT32_MIN
#define UINT_FAST32_MAX UINT32_MAX
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
#define INT_FAST64_MAX INT64_MAX
#define INT_FAST64_MIN INT64_MIN
#define UINT_FAST64_MAX UINT64_MAX
#endif
#define INTPTR_MAX INT32_MAX
#define INTPTR_MIN INT32_MIN
#define UINTPTR_MAX UINT32_MAX
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
#elif defined(_TMS320C5XX) || defined(__TMS320C27X__) || defined(__MSP430__)
#define INTMAX_MIN INT32_MIN
#define INTMAX_MAX INT32_MAX
#define UINTMAX_MAX UINT32_MAX
#endif
/* 7.18.3 Limits of other integer types */
#define PTRDIFF_MAX INT32_MAX
#define PTRDIFF_MIN INT32_MIN
#define SIG_ATOMIC_MIN INT32_MIN
#define SIG_ATOMIC_MAX INT32_MAX
#define SIZE_MAX INT32_MAX
#ifndef WCHAR_MAX
#define WCHAR_MAX 0xffffu
#endif
#ifndef WCHAR_MIN
#define WCHAR_MIN 0
#endif
#define WINT_MIN INT32_MIN
#define WINT_MAX INT32_MAX
/* 7.18.4.1 Macros for minimum-width integer constants */
/*
There is a defect report filed against the C99 standard concerning how
the (U)INTN_C macros should be implemented. Please refer to --
http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_209.htm
for more information. These macros are implemented according to the
suggestion given at this web site.
*/
#define INT8_C(value) ((int_least8_t)(value))
#define UINT8_C(value) ((uint_least8_t)(value))
#define INT16_C(value) ((int_least16_t)(value))
#define UINT16_C(value) ((uint_least16_t)(value))
#define INT32_C(value) ((int_least32_t)(value))
#define UINT32_C(value) ((uint_least32_t)(value))
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
#define INT64_C(value) ((int_least64_t)(value))
#define UINT64_C(value) ((uint_least64_t)(value))
#endif
/* 7.18.4.2 Macros for greatest-width integer constants */
#define INTMAX_C(value) ((intmax_t)(value))
#define UINTMAX_C(value) ((uintmax_t)(value))
#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */
#endif /* _STDINT_H_ */

@ -0,0 +1,29 @@
cpp_src = $(wildcard *.cpp)
#cpp_src += $(wildcard ./utils/*.cpp)
#cpp_src += $(wildcard ./driver/*.cpp)
cpp_obj = $(cpp_src:.cpp=.o)
c_obj = $(c_src:.c=.o)
CC = g++
CFLAGS = -Wall -pedantic -li2c
LDFLAGS =
EXEC = runtest
all : $(EXEC)
$(EXEC): $(cpp_obj) $(c_obj)
$(CC) -o $@ $^ $(LDFLAGS)
debug : $(EXEC)
$(EXEC): $(cpp_obj) $(c_obj)
$(CC) -g -o $@ $^ $(LDFLAGS)
clean:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear
cleanall:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear

@ -0,0 +1,42 @@
#ifndef __HW_PLATTFORM_HPP__
#define __HW_PLATTFORM_HPP__
#include <iostream>
//
// csl ressources
//
#include "./../csl/implementations/dummy/dummy_pin.hpp"
//
// drivers
//
#include "./../drivers/LED.hpp"
struct HW_plattform
{
HW_plattform():
pin_0(),
pin_1(),
led_0(pin_0)
{}
void init()
{
std::cout << "bsl init..." << std::endl;
pin_0.set(false);
pin_1.set(false);
std::cout << "...done!" << std::endl;
};
private:
Dummy_Pin pin_0, pin_1;
public:
LED<Dummy_Pin> led_0;
};
#endif // __HW_PLATTFORM_HPP__

@ -0,0 +1,37 @@
#ifndef __AVR_PIN_HPP__
#define __AVR_PIN_HPP__
#include <iostream>
#include "./../../interfaces/pin.hpp"
struct AVR_Pin : Pin<AVR_Pin>
{
AVR_Pin()
{
std::cout << "created AVR_Pin" << std::endl;
}
void setImp(bool logic)
{
std::cout << "AVR pin set to " << logic << std::endl;
}
void toggleImp()
{
std::cout << "toggled AVR pin" << std::endl;
}
bool getImp()
{
return true;
}
void avr_stuff()
{
std::cout << "AVR specific stuff" << std::endl;
}
};
#endif // __AVR_PIN_HPP__

@ -0,0 +1,38 @@
#ifndef __DUMMY_PIN_HPP__
#define __DUMMY_PIN_HPP__
#include "./../../interfaces/pin.hpp"
#include <iostream>
struct Dummy_Pin : Pin<Dummy_Pin>
{
Dummy_Pin()
{
std::cout << "created Dummy_Pin" << std::endl;
}
void setImp(bool logic)
{
std::cout << "Dummy pin set to " << logic << std::endl;
}
void toggleImp()
{
std::cout << "toggled Dummy pin" << std::endl;
}
bool getImp()
{
return true;
}
void dummy_stuff()
{
std::cout << "dummy specific stuff" << std::endl;
}
};
#endif // __DUMMY_PIN_HPP__

@ -0,0 +1,37 @@
#ifndef __STM_PIN_HPP__
#define __STM_PIN_HPP__
#include "./../../interfaces/pin.hpp"
#include <iostream>
truct STM32_Pin : Pin<STM32_Pin>
{
STM32_Pin()
{
std::cout << "created STM32_Pin" << std::endl;
}
void setImp(bool logic)
{
std::cout << "stm32 pin set to " << logic << std::endl;
}
void toggleImp()
{
std::cout << "toggled stm32 pin" << std::endl;
}
bool getImp()
{
return true;
}
void STM32_stuff()
{
std::cout << "STM_32 specific stuff" << std::endl;
}
};
#endif // __STM_PIN_HPP__

@ -0,0 +1,23 @@
#ifndef __PIN_HPP__
#define __PIN_HPP__
template <typename Derived>
struct Pin
{
void set(bool logic)
{
static_cast<Derived*>(this)->setImp(logic);
}
void toggle()
{
static_cast<Derived*>(this)->toggleImp();
}
bool get(void)
{
return static_cast<Derived*>(this)->getImp();
}
};
#endif // __PIN_HPP__

@ -0,0 +1,35 @@
#ifndef __LED_HPP__
#define __LED_HPP__
#include "./../csl/interfaces/pin.hpp"
template <typename T>
class LED
{
public:
LED(Pin<T>& pin) :
pin(pin)
{}
void turnOn()
{
pin.set(true);
}
void turnOff()
{
pin.set(false);
}
void toggle()
{
pin.toggle();
}
private:
Pin<T>& pin;
};
#endif // __LED_HPP__

@ -0,0 +1,16 @@
#include <iostream>
#include "./bsl/hw_plattform.hpp"
int main()
{
HW_plattform hw;
hw.init();
//hw.pin_1.set(true);
hw.led_0.turnOn();
return 1;
}

Binary file not shown.

@ -0,0 +1,24 @@
cpp_src = $(wildcard *.cpp)
cpp_src += $(wildcard ./utils/*.cpp)
cpp_src += $(wildcard ./driver/*.cpp)
cpp_obj = $(cpp_src:.cpp=.o)
c_obj = $(c_src:.c=.o)
CC = g++
CFLAGS = -Wall -pedantic -li2c
LDFLAGS =
EXEC = runtest
all : $(EXEC)
$(EXEC): $(cpp_obj) $(c_obj)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear
cleanall:
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
clear

@ -0,0 +1,69 @@
#include "device.hpp"
#include <iostream>
Device::Device() :
reg_control(0x00)
{
std::cout << "Device::Device()" << std::endl;
std::cout << +reg_control.raw << std::endl;
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_OFF;
reg_control.bits.SPEED = Reg_Control::SPEED::STAND_STILL;
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
std::cout << "SPEED = " <<+reg_control.bits.SPEED << std::endl;
}
void Device::doSomething()
{
std::cout << "Device::doSomething()" << std::endl;
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
reg_control.bits.SPEED = Reg_Control::SPEED::FAST;
if(reg_control.bits.POWER_DEV == Reg_Control::POWER_DEV::TURN_ON){
std::cout << "device turned on!" << std::endl;
}
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
std::cout << +reg_control << std::endl;
reg_control = 0;
std::cout << +reg_control << std::endl;
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
//reg_control.bits.SPEED = Reg_Control::SPEED::FAST;
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
}
void Device::status()
{
// imitating read hardware register (for example reading from device via SPI or i2c)
reg_motorStatus = 0xFE;
if(reg_motorStatus.bits.POWER == Reg_MotorStatus::POWER::ON) {
std::cout << "Motor is Powered ON!" << std::endl;
} else {
std::cout << "Motor is Powered OFF!" << std::endl;
}
// will throw error because this bitfield is set const!
//reg_motorStatus.bits.STATUS = Reg_MotorStatus::STATUS::STANDSTILL;
std::cout << +reg_motorStatus.bits.POWER << std::endl;
std::cout << "Motor Status : " << +reg_motorStatus.bits.STATUS << std::endl;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save