diff --git a/.gitignore b/.gitignore index 638d150..97068ce 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ # vim swp files *.swp + +./.vscode/* diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d0fbac9 --- /dev/null +++ b/.vscode/settings.json @@ -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" + } +} \ No newline at end of file diff --git a/CPP/CRTP/example/Makefile b/CPP/CRTP/example/Makefile new file mode 100644 index 0000000..578bada --- /dev/null +++ b/CPP/CRTP/example/Makefile @@ -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 diff --git a/CPP/CRTP/example/main.cpp b/CPP/CRTP/example/main.cpp new file mode 100644 index 0000000..0606775 --- /dev/null +++ b/CPP/CRTP/example/main.cpp @@ -0,0 +1,148 @@ +#include +#include + +// https://www.modernescpp.com/index.php/c-is-still-lazy + +// +// CRTP base class of pin +// + +/* + avoiding virtual call (static polymorphism) +*/ + +template +struct PinBase +{ + void set(bool logic) + { + static_cast(this)->setImp(logic); + } + + void toggle() + { + static_cast(this)->toggleImp(); + } + + bool get(void) + { + return static_cast(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() + { + 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() + { + 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 +void foo(T& base) +{ + base.set(true); + base.set(false); + base.toggle(); +} + +template +void baa(PinBase& 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; +} \ No newline at end of file diff --git a/CPP/CRTP/example/runtest b/CPP/CRTP/example/runtest new file mode 100755 index 0000000..6679d54 Binary files /dev/null and b/CPP/CRTP/example/runtest differ diff --git a/CPP/CRTP/idea.cpp b/CPP/CRTP/idea.cpp new file mode 100644 index 0000000..7efae06 --- /dev/null +++ b/CPP/CRTP/idea.cpp @@ -0,0 +1,204 @@ +#include +#include + +// 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 +struct PinBase : public IPin +{ + void set(bool logic) + { + static_cast(this)->setImp(logic); + } + + void toggle() + { + static_cast(this)->toggleImp(); + } + + bool get(void) + { + return static_cast(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() + { + //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() + { + 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 +void foo(T& base) +{ + base.set(true); + base.set(false); + base.toggle(); +} + +template +void baa(PinBase& pin) +{ + pin.toggle(); + //foo(pin); +} + +#if 0 +template +struct Driver +{ + Driver(PinBase& pin) : pin(pin) + { + + } + + void doSomething() + { + pin.toggle(); + } + + private: + + PinBase 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; +} \ No newline at end of file diff --git a/CPP/CRTP/infos.txt b/CPP/CRTP/infos.txt new file mode 100644 index 0000000..cf15738 --- /dev/null +++ b/CPP/CRTP/infos.txt @@ -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 diff --git a/CPP/multithreading/Makefile b/CPP/multithreading/Makefile new file mode 100644 index 0000000..fe7ddc7 --- /dev/null +++ b/CPP/multithreading/Makefile @@ -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 diff --git a/CPP/multithreading/main.cpp b/CPP/multithreading/main.cpp new file mode 100644 index 0000000..4fb1da5 --- /dev/null +++ b/CPP/multithreading/main.cpp @@ -0,0 +1,77 @@ +#include + +#include +#include +#include +#include +#include + +pthread_mutex_t print_mtx; + +class IThread +{ + public: + + private: + + virtual void* _run() = 0; + + static void* _staticRun(void* context) + { + return static_cast(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; +} + diff --git a/CPP/multithreading/runtest b/CPP/multithreading/runtest new file mode 100755 index 0000000..4ca9068 Binary files /dev/null and b/CPP/multithreading/runtest differ diff --git a/CPP/register_modeling/.vscode/settings.json b/CPP/register_modeling/.vscode/settings.json new file mode 100644 index 0000000..d0fbac9 --- /dev/null +++ b/CPP/register_modeling/.vscode/settings.json @@ -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" + } +} \ No newline at end of file diff --git a/CPP/register_modeling/example_project/Makefile b/CPP/register_modeling/example_project/Makefile new file mode 100644 index 0000000..38e5ad5 --- /dev/null +++ b/CPP/register_modeling/example_project/Makefile @@ -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 diff --git a/CPP/register_modeling/example_project/driver/device.cpp b/CPP/register_modeling/example_project/driver/device.cpp index 4647a0c..715bf1e 100644 --- a/CPP/register_modeling/example_project/driver/device.cpp +++ b/CPP/register_modeling/example_project/driver/device.cpp @@ -1,14 +1,69 @@ #include "device.hpp" +#include -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; } \ No newline at end of file diff --git a/CPP/register_modeling/example_project/driver/device.hpp b/CPP/register_modeling/example_project/driver/device.hpp index 5fd0a01..2f9e1ea 100644 --- a/CPP/register_modeling/example_project/driver/device.hpp +++ b/CPP/register_modeling/example_project/driver/device.hpp @@ -1,7 +1,7 @@ #ifndef _DEVICE_HPP_ #define _DEVICE_HPP_ -#include"../BitField.hpp" +#include "../utils/BitField.hpp" #include #include @@ -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 bits; + typedef BitField Bits; enum{TURN_OFF = 0, TURN_ON = 1}; }; // bits 2-3 struct SPEED{ - typedef Bits bits; + typedef BitField 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 Bits; + enum{OFF = 0, ON = 1}; + }; + struct STATUS{ + typedef BitFieldBits; + 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_ diff --git a/CPP/register_modeling/example_project/main.cpp b/CPP/register_modeling/example_project/main.cpp index ab73c2a..ea510f1 100644 --- a/CPP/register_modeling/example_project/main.cpp +++ b/CPP/register_modeling/example_project/main.cpp @@ -1,9 +1,57 @@ #include +#include -#include "mcp4725/mcp4725.hpp" +#include "./driver/device.hpp" +#include "./utils/BitField.hpp" + +#ifdef SIMPLE_TEST int main(void) { + std::cout << "test" << std::endl; + + BitField bitfield_0; + BitField bitfield_1; + + + std::cout << "testing bitfield 0" << std::endl; + + for(uint8_t i = 0; i < 10; i++) { + + bitfield_0 = i; + std::cout << static_cast(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(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; -} \ No newline at end of file +} diff --git a/CPP/register_modeling/example_project/mcp4725/mcp4725.cpp b/CPP/register_modeling/example_project/mcp4725/mcp4725.cpp deleted file mode 100644 index 96c3e17..0000000 --- a/CPP/register_modeling/example_project/mcp4725/mcp4725.cpp +++ /dev/null @@ -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(dac_value >> 4); - temp[2] = static_cast(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(dac_value >> 4); - temp[2] = static_cast(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(dac_value >> 4); - temp[2] = static_cast(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(dac_value >> 4); - temp[2] = static_cast(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(dac_and_eeprom_value >> 4); - temp[2] = static_cast(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 diff --git a/CPP/register_modeling/example_project/mcp4725/mcp4725.hpp b/CPP/register_modeling/example_project/mcp4725/mcp4725.hpp deleted file mode 100644 index dbd3922..0000000 --- a/CPP/register_modeling/example_project/mcp4725/mcp4725.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef _MCP4725_HPP_ -#define _MCP4725_HPP_ - -#include -#include -#include -#include "../../communication/i2c/i2c.hpp" - -class MCP4725 -{ - public: - //typedef std::function i2c_write_n_t; - //typedef std::function i2c_write_n_t; - //typedef void(*i2c_write_n_t)(const uint8_t&, const uint8_t*, const uint8_t&); - - //typedef std::functioni2c_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 i2c_read_n_t; - - //using i2c_write_n_t = std::functional; - - /** - * @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_ diff --git a/CPP/register_modeling/example_project/problem_test.txt b/CPP/register_modeling/example_project/problem_test.txt new file mode 100644 index 0000000..ed7d1ee --- /dev/null +++ b/CPP/register_modeling/example_project/problem_test.txt @@ -0,0 +1,126 @@ +// Example program +#include +#include + + +#include + +/** + * @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 +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 Bits; + enum{TURN_OFF = 0, TURN_ON = 1}; + }; + // bits 2-3 + struct SPEED{ + typedef BitField 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; +} \ No newline at end of file diff --git a/CPP/register_modeling/example_project/runtest b/CPP/register_modeling/example_project/runtest new file mode 100755 index 0000000..5dfe56a Binary files /dev/null and b/CPP/register_modeling/example_project/runtest differ diff --git a/CPP/register_modeling/example_project/BitField.hpp b/CPP/register_modeling/example_project/utils/BitField.hpp similarity index 81% rename from CPP/register_modeling/example_project/BitField.hpp rename to CPP/register_modeling/example_project/utils/BitField.hpp index c3431dd..7b36c16 100644 --- a/CPP/register_modeling/example_project/BitField.hpp +++ b/CPP/register_modeling/example_project/utils/BitField.hpp @@ -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 /** @@ -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_ \ No newline at end of file diff --git a/CPP/register_modeling/example_with_STM32_GPIO/Makefile b/CPP/register_modeling/example_with_STM32_GPIO/Makefile new file mode 100644 index 0000000..38e5ad5 --- /dev/null +++ b/CPP/register_modeling/example_with_STM32_GPIO/Makefile @@ -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 diff --git a/CPP/register_modeling/example_with_STM32_GPIO/main.cpp b/CPP/register_modeling/example_with_STM32_GPIO/main.cpp new file mode 100644 index 0000000..1a2f615 --- /dev/null +++ b/CPP/register_modeling/example_with_STM32_GPIO/main.cpp @@ -0,0 +1,105 @@ +#include +#include + +#include "utils/BitField.hpp" + + + +union GPIO_MODER +{ + struct MODER{ + enum{ + INPUT_MODE, + OUTPUT, + ALT_FUNCTION, + ANALOG + }; + }; + + struct MODER_0 : public MODER{ + typedef BitField Bits; + }; + struct MODER_1 : public MODER{ + typedef BitField Bits; + }; + struct MODER_2 : public MODER{ + typedef BitField Bits; + }; + struct MODER_3 : public MODER{ + typedef BitField Bits; + }; + struct MODER_4 : public MODER{ + typedef BitField Bits; + }; + struct MODER_5 : public MODER{ + typedef BitField Bits; + }; + struct MODER_6 : public MODER{ + typedef BitField Bits; + }; + struct MODER_7 : public MODER{ + typedef BitField Bits; + }; + struct MODER_8 : public MODER{ + typedef BitField Bits; + }; + struct MODER_9 : public MODER{ + typedef BitField Bits; + }; + struct MODER_10 : public MODER{ + typedef BitField Bits; + }; + struct MODER_11 : public MODER{ + typedef BitField Bits; + }; + struct MODER_12 : public MODER{ + typedef BitField Bits; + }; + struct MODER_13 : public MODER{ + typedef BitField Bits; + }; + struct MODER_14 : public MODER{ + typedef BitField Bits; + }; + struct MODER_15 : public MODER{ + typedef BitField 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; +} \ No newline at end of file diff --git a/CPP/register_modeling/example_with_STM32_GPIO/runtest b/CPP/register_modeling/example_with_STM32_GPIO/runtest new file mode 100755 index 0000000..6aa3385 Binary files /dev/null and b/CPP/register_modeling/example_with_STM32_GPIO/runtest differ diff --git a/CPP/register_modeling/example_with_STM32_GPIO/utils/BitField.hpp b/CPP/register_modeling/example_with_STM32_GPIO/utils/BitField.hpp new file mode 100644 index 0000000..7b36c16 --- /dev/null +++ b/CPP/register_modeling/example_with_STM32_GPIO/utils/BitField.hpp @@ -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 + +/** + * @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 +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_ \ No newline at end of file diff --git a/CPP/register_modeling/portable_bitfields/BitField.h b/CPP/register_modeling/portable_bitfields/BitField.h index c3431dd..a826b6c 100644 --- a/CPP/register_modeling/portable_bitfields/BitField.h +++ b/CPP/register_modeling/portable_bitfields/BitField.h @@ -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: diff --git a/CodeTutorials/300-FSM/00-Zustandsbasierte_Systeme.pdf b/CodeTutorials/300-FSM/00-Zustandsbasierte_Systeme.pdf new file mode 100644 index 0000000..61fb7e1 Binary files /dev/null and b/CodeTutorials/300-FSM/00-Zustandsbasierte_Systeme.pdf differ diff --git a/CodeTutorials/300-FSM/10-Statecharts(Marwedel).pdf b/CodeTutorials/300-FSM/10-Statecharts(Marwedel).pdf new file mode 100644 index 0000000..81d6b7e Binary files /dev/null and b/CodeTutorials/300-FSM/10-Statecharts(Marwedel).pdf differ diff --git a/CodeTutorials/300-FSM/20-Harel_Statecharts.pdf b/CodeTutorials/300-FSM/20-Harel_Statecharts.pdf new file mode 100644 index 0000000..8879160 Binary files /dev/null and b/CodeTutorials/300-FSM/20-Harel_Statecharts.pdf differ diff --git a/CodeTutorials/320-FSM_Realisierung/00-FSM-Realisierung.pdf b/CodeTutorials/320-FSM_Realisierung/00-FSM-Realisierung.pdf new file mode 100644 index 0000000..eea281d Binary files /dev/null and b/CodeTutorials/320-FSM_Realisierung/00-FSM-Realisierung.pdf differ diff --git a/CodeTutorials/320-FSM_Realisierung/10-FSM-Realisierung.pdf b/CodeTutorials/320-FSM_Realisierung/10-FSM-Realisierung.pdf new file mode 100644 index 0000000..8beb42d Binary files /dev/null and b/CodeTutorials/320-FSM_Realisierung/10-FSM-Realisierung.pdf differ diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counter.c b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counter.c new file mode 100644 index 0000000..34867eb --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counter.c @@ -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; +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counter.h b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counter.h new file mode 100644 index 0000000..7c4b9a9 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counter.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterCtrl.c b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterCtrl.c new file mode 100644 index 0000000..53f1288 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterCtrl.c @@ -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 +#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; + } +} + diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterCtrl.h b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterCtrl.h new file mode 100644 index 0000000..e369bef --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterCtrl.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterTest b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterTest new file mode 100644 index 0000000..f9aa282 Binary files /dev/null and b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterTest differ diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterTest.c b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterTest.c new file mode 100644 index 0000000..7d5d327 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterTest.c @@ -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 +#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; +} + diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterTest.c~ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterTest.c~ new file mode 100644 index 0000000..a3a2611 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/counterTest.c~ @@ -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 +#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; +} + diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/makefile b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/makefile new file mode 100644 index 0000000..6818838 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_C/makefile @@ -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) diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/Counter.cpp b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/Counter.cpp new file mode 100644 index 0000000..2054287 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/Counter.cpp @@ -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; +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/Counter.h b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/Counter.h new file mode 100644 index 0000000..a00c2b7 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/Counter.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/CounterCtrl.cpp b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/CounterCtrl.cpp new file mode 100644 index 0000000..679258c --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/CounterCtrl.cpp @@ -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 +#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; + } +} + diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/CounterCtrl.h b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/CounterCtrl.h new file mode 100644 index 0000000..4ad29c8 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/CounterCtrl.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/counterTest b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/counterTest new file mode 100644 index 0000000..d210c9b Binary files /dev/null and b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/counterTest differ diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/counterTest.cpp b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/counterTest.cpp new file mode 100644 index 0000000..ac3ba85 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/counterTest.cpp @@ -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 +#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; +} + diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/counterTest.exe b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/counterTest.exe new file mode 100644 index 0000000..a5ebdaa Binary files /dev/null and b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/counterTest.exe differ diff --git a/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/makefile b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/makefile new file mode 100644 index 0000000..2bea153 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Ctrl_Cpp/makefile @@ -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) diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern/Counter.cpp b/CodeTutorials/320-FSM_Realisierung/src/Pattern/Counter.cpp new file mode 100644 index 0000000..2054287 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern/Counter.cpp @@ -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; +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern/Counter.h b/CodeTutorials/320-FSM_Realisierung/src/Pattern/Counter.h new file mode 100644 index 0000000..0823cd7 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern/Counter.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterCtrl.cpp b/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterCtrl.cpp new file mode 100644 index 0000000..bc6915f --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterCtrl.cpp @@ -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); +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterCtrl.h b/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterCtrl.h new file mode 100644 index 0000000..6840ee5 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterCtrl.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterState.cpp b/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterState.cpp new file mode 100644 index 0000000..b52f7fa --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterState.cpp @@ -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 +#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; +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterState.h b/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterState.h new file mode 100644 index 0000000..0728f21 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern/CounterState.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern/counterTest.cpp b/CodeTutorials/320-FSM_Realisierung/src/Pattern/counterTest.cpp new file mode 100644 index 0000000..db2baba --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern/counterTest.cpp @@ -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 +#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; +} + diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern/counterTest.exe b/CodeTutorials/320-FSM_Realisierung/src/Pattern/counterTest.exe new file mode 100644 index 0000000..09e374c Binary files /dev/null and b/CodeTutorials/320-FSM_Realisierung/src/Pattern/counterTest.exe differ diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern/makefile b/CodeTutorials/320-FSM_Realisierung/src/Pattern/makefile new file mode 100644 index 0000000..2efec34 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern/makefile @@ -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) diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/.vscode/settings.json b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/.vscode/settings.json new file mode 100644 index 0000000..38991d9 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.associations": { + "xmemory": "cpp", + "xstring": "cpp" + } +} \ No newline at end of file diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/Counter.cpp b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/Counter.cpp new file mode 100644 index 0000000..eb6cdf6 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/Counter.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; +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/Counter.h b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/Counter.h new file mode 100644 index 0000000..7442f76 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/Counter.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterCtrl.cpp b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterCtrl.cpp new file mode 100644 index 0000000..fd638eb --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterCtrl.cpp @@ -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 +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterCtrl.h b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterCtrl.h new file mode 100644 index 0000000..3bffe53 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterCtrl.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterState.cpp b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterState.cpp new file mode 100644 index 0000000..c41df71 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterState.cpp @@ -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 +#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; +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterState.h b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterState.h new file mode 100644 index 0000000..9e08021 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/CounterState.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/counterTest.cpp b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/counterTest.cpp new file mode 100644 index 0000000..e2be939 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/counterTest.cpp @@ -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 +#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; +} + diff --git a/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/makefile b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/makefile new file mode 100644 index 0000000..7c653f0 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Pattern_Action/makefile @@ -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) diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table/Counter.cpp b/CodeTutorials/320-FSM_Realisierung/src/Table/Counter.cpp new file mode 100644 index 0000000..2054287 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table/Counter.cpp @@ -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; +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table/Counter.h b/CodeTutorials/320-FSM_Realisierung/src/Table/Counter.h new file mode 100644 index 0000000..84e2055 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table/Counter.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table/CounterCtrl.cpp b/CodeTutorials/320-FSM_Realisierung/src/Table/CounterCtrl.cpp new file mode 100644 index 0000000..10772c9 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table/CounterCtrl.cpp @@ -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 +#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; +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table/CounterCtrl.h b/CodeTutorials/320-FSM_Realisierung/src/Table/CounterCtrl.h new file mode 100644 index 0000000..248cdde --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table/CounterCtrl.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table/counterTest b/CodeTutorials/320-FSM_Realisierung/src/Table/counterTest new file mode 100644 index 0000000..f5b1d62 Binary files /dev/null and b/CodeTutorials/320-FSM_Realisierung/src/Table/counterTest differ diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table/counterTest.cpp b/CodeTutorials/320-FSM_Realisierung/src/Table/counterTest.cpp new file mode 100644 index 0000000..a66cdfc --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table/counterTest.cpp @@ -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 +#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; +} + diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table/counterTest.exe b/CodeTutorials/320-FSM_Realisierung/src/Table/counterTest.exe new file mode 100644 index 0000000..6f4a055 Binary files /dev/null and b/CodeTutorials/320-FSM_Realisierung/src/Table/counterTest.exe differ diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table/makefile b/CodeTutorials/320-FSM_Realisierung/src/Table/makefile new file mode 100644 index 0000000..dac2246 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table/makefile @@ -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) diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/Counter.cpp b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/Counter.cpp new file mode 100644 index 0000000..2054287 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/Counter.cpp @@ -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; +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/Counter.h b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/Counter.h new file mode 100644 index 0000000..84e2055 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/Counter.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/CounterCtrl.cpp b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/CounterCtrl.cpp new file mode 100644 index 0000000..9d8134d --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/CounterCtrl.cpp @@ -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 +#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; +} diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/CounterCtrl.h b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/CounterCtrl.h new file mode 100644 index 0000000..986fe20 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/CounterCtrl.h @@ -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 diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/counterTest b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/counterTest new file mode 100644 index 0000000..bd911fa Binary files /dev/null and b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/counterTest differ diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/counterTest.cpp b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/counterTest.cpp new file mode 100644 index 0000000..db2baba --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/counterTest.cpp @@ -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 +#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; +} + diff --git a/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/makefile b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/makefile new file mode 100644 index 0000000..dac2246 --- /dev/null +++ b/CodeTutorials/320-FSM_Realisierung/src/Table_Simple/makefile @@ -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) diff --git a/CodeTutorials/600-Advanced-C++/00-Advanced_and_Effective-C++.pdf b/CodeTutorials/600-Advanced-C++/00-Advanced_and_Effective-C++.pdf new file mode 100644 index 0000000..cd82cd1 Binary files /dev/null and b/CodeTutorials/600-Advanced-C++/00-Advanced_and_Effective-C++.pdf differ diff --git a/CodeTutorials/600-Advanced-C++/10-effCppEmbNotes2015-04-02.pdf b/CodeTutorials/600-Advanced-C++/10-effCppEmbNotes2015-04-02.pdf new file mode 100644 index 0000000..7da45e6 Binary files /dev/null and b/CodeTutorials/600-Advanced-C++/10-effCppEmbNotes2015-04-02.pdf differ diff --git a/CodeTutorials/600-Advanced-C++/15-Optimizing Code for Stellaris.pdf b/CodeTutorials/600-Advanced-C++/15-Optimizing Code for Stellaris.pdf new file mode 100644 index 0000000..b3ec4b6 Binary files /dev/null and b/CodeTutorials/600-Advanced-C++/15-Optimizing Code for Stellaris.pdf differ diff --git a/CodeTutorials/600-Advanced-C++/20-Implementing_Virtual_Functions.pdf b/CodeTutorials/600-Advanced-C++/20-Implementing_Virtual_Functions.pdf new file mode 100644 index 0000000..8d91c5e Binary files /dev/null and b/CodeTutorials/600-Advanced-C++/20-Implementing_Virtual_Functions.pdf differ diff --git a/CodeTutorials/600-Advanced-C++/30-Avoiding_Code_Data_Bloat.pdf b/CodeTutorials/600-Advanced-C++/30-Avoiding_Code_Data_Bloat.pdf new file mode 100644 index 0000000..979f9b6 Binary files /dev/null and b/CodeTutorials/600-Advanced-C++/30-Avoiding_Code_Data_Bloat.pdf differ diff --git a/CodeTutorials/600-Advanced-C++/40-Interface_Based_Programming.pdf b/CodeTutorials/600-Advanced-C++/40-Interface_Based_Programming.pdf new file mode 100644 index 0000000..ae2c917 Binary files /dev/null and b/CodeTutorials/600-Advanced-C++/40-Interface_Based_Programming.pdf differ diff --git a/CodeTutorials/600-Advanced-C++/50-Dynamic_Memory_Management.pdf b/CodeTutorials/600-Advanced-C++/50-Dynamic_Memory_Management.pdf new file mode 100644 index 0000000..3f93cd4 Binary files /dev/null and b/CodeTutorials/600-Advanced-C++/50-Dynamic_Memory_Management.pdf differ diff --git a/CodeTutorials/600-Advanced-C++/60-C++_and_ROMability.pdf b/CodeTutorials/600-Advanced-C++/60-C++_and_ROMability.pdf new file mode 100644 index 0000000..eb112a3 Binary files /dev/null and b/CodeTutorials/600-Advanced-C++/60-C++_and_ROMability.pdf differ diff --git a/CodeTutorials/600-Advanced-C++/70-Modeling_MMIO.pdf b/CodeTutorials/600-Advanced-C++/70-Modeling_MMIO.pdf new file mode 100644 index 0000000..894e2ad Binary files /dev/null and b/CodeTutorials/600-Advanced-C++/70-Modeling_MMIO.pdf differ diff --git a/CodeTutorials/600-Advanced-C++/src/TIHeaders/stdint.h b/CodeTutorials/600-Advanced-C++/src/TIHeaders/stdint.h new file mode 100644 index 0000000..cbebffb --- /dev/null +++ b/CodeTutorials/600-Advanced-C++/src/TIHeaders/stdint.h @@ -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 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_ */ diff --git a/KED_structure_idea/Makefile b/KED_structure_idea/Makefile new file mode 100644 index 0000000..db99c6d --- /dev/null +++ b/KED_structure_idea/Makefile @@ -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 diff --git a/KED_structure_idea/bsl/hw_plattform.hpp b/KED_structure_idea/bsl/hw_plattform.hpp new file mode 100644 index 0000000..31d711d --- /dev/null +++ b/KED_structure_idea/bsl/hw_plattform.hpp @@ -0,0 +1,42 @@ +#ifndef __HW_PLATTFORM_HPP__ +#define __HW_PLATTFORM_HPP__ + +#include + +// +// 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 led_0; +}; + + +#endif // __HW_PLATTFORM_HPP__ diff --git a/KED_structure_idea/csl/implementations/avr/avr_pin.hpp b/KED_structure_idea/csl/implementations/avr/avr_pin.hpp new file mode 100644 index 0000000..42c49ec --- /dev/null +++ b/KED_structure_idea/csl/implementations/avr/avr_pin.hpp @@ -0,0 +1,37 @@ +#ifndef __AVR_PIN_HPP__ +#define __AVR_PIN_HPP__ + +#include +#include "./../../interfaces/pin.hpp" + + + +struct AVR_Pin : 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__ \ No newline at end of file diff --git a/KED_structure_idea/csl/implementations/dummy/dummy_pin.hpp b/KED_structure_idea/csl/implementations/dummy/dummy_pin.hpp new file mode 100644 index 0000000..96b1cb6 --- /dev/null +++ b/KED_structure_idea/csl/implementations/dummy/dummy_pin.hpp @@ -0,0 +1,38 @@ +#ifndef __DUMMY_PIN_HPP__ +#define __DUMMY_PIN_HPP__ + +#include "./../../interfaces/pin.hpp" + +#include + + +struct Dummy_Pin : 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__ diff --git a/KED_structure_idea/csl/implementations/stm/stm_pin.hpp b/KED_structure_idea/csl/implementations/stm/stm_pin.hpp new file mode 100644 index 0000000..2d4cf74 --- /dev/null +++ b/KED_structure_idea/csl/implementations/stm/stm_pin.hpp @@ -0,0 +1,37 @@ +#ifndef __STM_PIN_HPP__ +#define __STM_PIN_HPP__ + +#include "./../../interfaces/pin.hpp" + +#include + +truct STM32_Pin : 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__ diff --git a/KED_structure_idea/csl/interfaces/pin.hpp b/KED_structure_idea/csl/interfaces/pin.hpp new file mode 100644 index 0000000..3c9c76d --- /dev/null +++ b/KED_structure_idea/csl/interfaces/pin.hpp @@ -0,0 +1,23 @@ +#ifndef __PIN_HPP__ +#define __PIN_HPP__ + +template +struct Pin +{ + void set(bool logic) + { + static_cast(this)->setImp(logic); + } + + void toggle() + { + static_cast(this)->toggleImp(); + } + + bool get(void) + { + return static_cast(this)->getImp(); + } +}; + +#endif // __PIN_HPP__ diff --git a/KED_structure_idea/drivers/LED.hpp b/KED_structure_idea/drivers/LED.hpp new file mode 100644 index 0000000..dfaec72 --- /dev/null +++ b/KED_structure_idea/drivers/LED.hpp @@ -0,0 +1,35 @@ +#ifndef __LED_HPP__ +#define __LED_HPP__ + +#include "./../csl/interfaces/pin.hpp" + +template +class LED +{ + public: + + LED(Pin& pin) : + pin(pin) + {} + + void turnOn() + { + pin.set(true); + } + + void turnOff() + { + pin.set(false); + } + + void toggle() + { + pin.toggle(); + } + + private: + + Pin& pin; +}; + +#endif // __LED_HPP__ diff --git a/KED_structure_idea/main.cpp b/KED_structure_idea/main.cpp new file mode 100644 index 0000000..522a52f --- /dev/null +++ b/KED_structure_idea/main.cpp @@ -0,0 +1,16 @@ +#include + +#include "./bsl/hw_plattform.hpp" + + +int main() +{ + HW_plattform hw; + hw.init(); + + //hw.pin_1.set(true); + + hw.led_0.turnOn(); + + return 1; +} \ No newline at end of file diff --git a/KED_structure_idea/runtest b/KED_structure_idea/runtest new file mode 100755 index 0000000..13f81ba Binary files /dev/null and b/KED_structure_idea/runtest differ diff --git a/driver_dev/max31865_dev/Makefile b/driver_dev/max31865_dev/Makefile new file mode 100644 index 0000000..38e5ad5 --- /dev/null +++ b/driver_dev/max31865_dev/Makefile @@ -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 diff --git a/driver_dev/max31865_dev/driver/device.cpp b/driver_dev/max31865_dev/driver/device.cpp new file mode 100644 index 0000000..715bf1e --- /dev/null +++ b/driver_dev/max31865_dev/driver/device.cpp @@ -0,0 +1,69 @@ +#include "device.hpp" +#include + +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; +} \ No newline at end of file diff --git a/driver_dev/max31865_dev/driver/device.hpp b/driver_dev/max31865_dev/driver/device.hpp new file mode 100644 index 0000000..2f9e1ea --- /dev/null +++ b/driver_dev/max31865_dev/driver/device.hpp @@ -0,0 +1,113 @@ +#ifndef _DEVICE_HPP_ +#define _DEVICE_HPP_ + +#include "../utils/BitField.hpp" + +#include +#include + +class Device +{ + public: + Device(); + + void doSomething(); + + void status(); + + private: + + // + // Register declarations + // +#ifdef EXAMPLE_CODE_FOR_REFERENCE + union Control { + struct OPM{ + typedef Bits bits; + enum { NO_CHANGE = 0, AS_STANDBY = 1}; + }; + struct CTRL_BR{ + enum { NO_CHANGE = 0, BRANCH_NORMAL = 1}; + }; + struct CTRL_BR1 : CTRL_BR{ + typedef Bits bits; + }; + struct CTRL_BR2 : CTRL_BR{ + typedef Bits bits; + }; + + union Bits { + Control::OPM::bits OPM; + Control::CTRL_BR1::bits CTRL_BR1; + Control::CTRL_BR2::bits CTRL_BR2; + } bits; + uint16_t raw; + }; +#endif + union Reg_Control + { + // bit 4 + struct POWER_DEV{ + typedef BitField Bits; + enum{TURN_OFF = 0, TURN_ON = 1}; + }; + // bits 2-3 + struct SPEED{ + typedef BitField 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) {} + // 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 Bits; + enum{OFF = 0, ON = 1}; + }; + struct STATUS{ + typedef BitFieldBits; + 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_ diff --git a/driver_dev/max31865_dev/driver/max31865.cpp b/driver_dev/max31865_dev/driver/max31865.cpp new file mode 100644 index 0000000..e69de29 diff --git a/driver_dev/max31865_dev/driver/max31865.hpp b/driver_dev/max31865_dev/driver/max31865.hpp new file mode 100644 index 0000000..908dc3f --- /dev/null +++ b/driver_dev/max31865_dev/driver/max31865.hpp @@ -0,0 +1,64 @@ +#ifdef __MAX31865_HPP_ +#define __MAX31865_HPP__ + +#include +#include "../utils/BitFiled.hpp" + + +class MAX31865 +{ + public: + MAX31865(); + + private: + + // + // register definitions + // + + union CONFIG_REG { + struct VBIAS{ + enum { + OFF = 0, + ON = 1 + }; + typedef BitField Bits; + }; + + struct CONVERSION_MODE{ + enum { + OFF = 0, + AUTO = 1 + }; + typedef BitField Bits; + }; + + struct ONE_SHOT{ + enum { + IDLE = 0, + SET = 1 + }; + typedef BitField Bits; + }; + + struct WIRING{ + enum { + TWO_OR_FOUR_WIRE = 0, + THREE_WIRE = 1 + }; + typedef BitField Bits; + }; + + struct { + enum { + IDLE = 0, + SET = 1 + }; + typedef BitField Bits; + }; + + }; +}; + + +#endif // __MAX31865_HPP__ diff --git a/driver_dev/max31865_dev/interfaces/i2c.cpp b/driver_dev/max31865_dev/interfaces/i2c.cpp new file mode 100644 index 0000000..e69de29 diff --git a/driver_dev/max31865_dev/interfaces/i2c.hpp b/driver_dev/max31865_dev/interfaces/i2c.hpp new file mode 100644 index 0000000..e69de29 diff --git a/driver_dev/max31865_dev/main.cpp b/driver_dev/max31865_dev/main.cpp new file mode 100644 index 0000000..ea510f1 --- /dev/null +++ b/driver_dev/max31865_dev/main.cpp @@ -0,0 +1,57 @@ +#include +#include + +#include "./driver/device.hpp" +#include "./utils/BitField.hpp" + +#ifdef SIMPLE_TEST + +int main(void) +{ + std::cout << "test" << std::endl; + + BitField bitfield_0; + BitField bitfield_1; + + + std::cout << "testing bitfield 0" << std::endl; + + for(uint8_t i = 0; i < 10; i++) { + + bitfield_0 = i; + std::cout << static_cast(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(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; +} diff --git a/driver_dev/max31865_dev/problem_test.txt b/driver_dev/max31865_dev/problem_test.txt new file mode 100644 index 0000000..ed7d1ee --- /dev/null +++ b/driver_dev/max31865_dev/problem_test.txt @@ -0,0 +1,126 @@ +// Example program +#include +#include + + +#include + +/** + * @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 +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 Bits; + enum{TURN_OFF = 0, TURN_ON = 1}; + }; + // bits 2-3 + struct SPEED{ + typedef BitField 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; +} \ No newline at end of file diff --git a/driver_dev/max31865_dev/runtest b/driver_dev/max31865_dev/runtest new file mode 100755 index 0000000..5dfe56a Binary files /dev/null and b/driver_dev/max31865_dev/runtest differ diff --git a/driver_dev/max31865_dev/utils/BitField.hpp b/driver_dev/max31865_dev/utils/BitField.hpp new file mode 100644 index 0000000..7b36c16 --- /dev/null +++ b/driver_dev/max31865_dev/utils/BitField.hpp @@ -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 + +/** + * @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 +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_ \ No newline at end of file diff --git a/scribbles_and_notes/pin_interface_CRTP_style/pin_modleing_with_CRTP/Makefile b/scribbles_and_notes/pin_interface_CRTP_style/pin_modleing_with_CRTP/Makefile new file mode 100644 index 0000000..38e5ad5 --- /dev/null +++ b/scribbles_and_notes/pin_interface_CRTP_style/pin_modleing_with_CRTP/Makefile @@ -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 diff --git a/scribbles_and_notes/pin_interface_CRTP_style/pin_modleing_with_CRTP/main.cpp b/scribbles_and_notes/pin_interface_CRTP_style/pin_modleing_with_CRTP/main.cpp new file mode 100644 index 0000000..4bbbd67 --- /dev/null +++ b/scribbles_and_notes/pin_interface_CRTP_style/pin_modleing_with_CRTP/main.cpp @@ -0,0 +1,138 @@ +#include +#include + +// https://www.modernescpp.com/index.php/c-is-still-lazy + +// +// CRTP base class of pin +// + +/* + avoiding virtual call (static polymorphism) +*/ + +template +struct PinBase +{ + void set(bool logic) + { + static_cast(this)->setImp(logic); + } + + void toggle() + { + static_cast(this)->toggleImp(); + } + + bool get(void) + { + return static_cast(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() + { + 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() + { + 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 +void foo(T& base) +{ + base.set(true); + base.set(false); + base.toggle(); +} + +int main(void) +{ + STM32_Pin pin1; + AVR_Pin pin2; + + + pin1.STM32_stuff(); + + pin2.avr_stuff(); + + foo(pin1); + foo(pin2); + + return 0; +} \ No newline at end of file diff --git a/scribbles_and_notes/pin_interface_CRTP_style/pin_modleing_with_CRTP/runtest b/scribbles_and_notes/pin_interface_CRTP_style/pin_modleing_with_CRTP/runtest new file mode 100755 index 0000000..12fab27 Binary files /dev/null and b/scribbles_and_notes/pin_interface_CRTP_style/pin_modleing_with_CRTP/runtest differ