Merge branch 'master' of https://git.keydev.me/edwin/ideas
commit
9139565f1d
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"*.tcc": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"typeinfo": "cpp"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
cpp_src = $(wildcard *.cpp)
|
||||||
|
cpp_src += $(wildcard ./utils/*.cpp)
|
||||||
|
cpp_src += $(wildcard ./driver/*.cpp)
|
||||||
|
|
||||||
|
cpp_obj = $(cpp_src:.cpp=.o)
|
||||||
|
c_obj = $(c_src:.c=.o)
|
||||||
|
CC = g++
|
||||||
|
CFLAGS = -Wall -pedantic -li2c
|
||||||
|
LDFLAGS =
|
||||||
|
EXEC = runtest
|
||||||
|
|
||||||
|
|
||||||
|
all : $(EXEC)
|
||||||
|
|
||||||
|
$(EXEC): $(cpp_obj) $(c_obj)
|
||||||
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
debug : $(EXEC)
|
||||||
|
|
||||||
|
$(EXEC): $(cpp_obj) $(c_obj)
|
||||||
|
$(CC) -g -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
||||||
|
|
||||||
|
cleanall:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
@ -0,0 +1,148 @@
|
|||||||
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// https://www.modernescpp.com/index.php/c-is-still-lazy
|
||||||
|
|
||||||
|
//
|
||||||
|
// CRTP base class of pin
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
avoiding virtual call (static polymorphism)
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
|
struct PinBase
|
||||||
|
{
|
||||||
|
void set(bool logic)
|
||||||
|
{
|
||||||
|
static_cast<Derived*>(this)->setImp(logic);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle()
|
||||||
|
{
|
||||||
|
static_cast<Derived*>(this)->toggleImp();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get(void)
|
||||||
|
{
|
||||||
|
return static_cast<Derived*>(this)->getImp();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//
|
||||||
|
// base implementations
|
||||||
|
//
|
||||||
|
|
||||||
|
void setImp()
|
||||||
|
{
|
||||||
|
std::cout << "base implementation of set()!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleImp()
|
||||||
|
{
|
||||||
|
std::cout << "base implementation of toggle()!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getImp(void)
|
||||||
|
{
|
||||||
|
std::cout << "base implementation of get()!" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// implementations
|
||||||
|
//
|
||||||
|
|
||||||
|
struct STM32_Pin : PinBase<STM32_Pin>
|
||||||
|
{
|
||||||
|
STM32_Pin()
|
||||||
|
{
|
||||||
|
std::cout << "created STM32_Pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setImp(bool logic)
|
||||||
|
{
|
||||||
|
std::cout << "stm32 pin set to " << logic << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleImp()
|
||||||
|
{
|
||||||
|
std::cout << "toggled stm32 pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getImp()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void STM32_stuff()
|
||||||
|
{
|
||||||
|
std::cout << "STM_32 specific stuff" << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AVR_Pin : PinBase<AVR_Pin>
|
||||||
|
{
|
||||||
|
AVR_Pin()
|
||||||
|
{
|
||||||
|
std::cout << "created AVR_Pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setImp(bool logic)
|
||||||
|
{
|
||||||
|
std::cout << "AVR pin set to " << logic << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleImp()
|
||||||
|
{
|
||||||
|
std::cout << "toggled AVR pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getImp()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_stuff()
|
||||||
|
{
|
||||||
|
std::cout << "AVR specific stuff" << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void foo(T& base)
|
||||||
|
{
|
||||||
|
base.set(true);
|
||||||
|
base.set(false);
|
||||||
|
base.toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void baa(PinBase<T>& pin)
|
||||||
|
{
|
||||||
|
pin.toggle();
|
||||||
|
//foo(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
STM32_Pin pin1;
|
||||||
|
AVR_Pin pin2;
|
||||||
|
|
||||||
|
pin1.STM32_stuff();
|
||||||
|
|
||||||
|
pin2.avr_stuff();
|
||||||
|
|
||||||
|
foo(pin1);
|
||||||
|
foo(pin2);
|
||||||
|
|
||||||
|
baa(pin1);
|
||||||
|
|
||||||
|
while(1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Binary file not shown.
@ -0,0 +1,204 @@
|
|||||||
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// https://www.modernescpp.com/index.php/c-is-still-lazy
|
||||||
|
|
||||||
|
//
|
||||||
|
// CRTP base class of pin
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
avoiding virtual call (static polymorphism)
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct IPin
|
||||||
|
{
|
||||||
|
void set(bool logic);
|
||||||
|
void toggle();
|
||||||
|
bool get();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
|
struct PinBase : public IPin
|
||||||
|
{
|
||||||
|
void set(bool logic)
|
||||||
|
{
|
||||||
|
static_cast<Derived*>(this)->setImp(logic);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle()
|
||||||
|
{
|
||||||
|
static_cast<Derived*>(this)->toggleImp();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get(void)
|
||||||
|
{
|
||||||
|
return static_cast<Derived*>(this)->getImp();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//
|
||||||
|
// base implementations
|
||||||
|
//
|
||||||
|
|
||||||
|
void setImp()
|
||||||
|
{
|
||||||
|
std::cout << "base implementation of set()!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleImp()
|
||||||
|
{
|
||||||
|
std::cout << "base implementation of toggle()!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getImp(void)
|
||||||
|
{
|
||||||
|
std::cout << "base implementation of get()!" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// implementations
|
||||||
|
//
|
||||||
|
|
||||||
|
struct STM32_Pin : PinBase<STM32_Pin>
|
||||||
|
{
|
||||||
|
STM32_Pin()
|
||||||
|
{
|
||||||
|
//std::cout << "created STM32_Pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setImp(bool logic)
|
||||||
|
{
|
||||||
|
//std::cout << "stm32 pin set to " << logic << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleImp()
|
||||||
|
{
|
||||||
|
//std::cout << "toggled stm32 pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getImp()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void STM32_stuff()
|
||||||
|
{
|
||||||
|
//std::cout << "STM_32 specific stuff" << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AVR_Pin : PinBase<AVR_Pin>
|
||||||
|
{
|
||||||
|
AVR_Pin()
|
||||||
|
{
|
||||||
|
a = 3;
|
||||||
|
//std::cout << "created AVR_Pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setImp(bool logic)
|
||||||
|
{
|
||||||
|
//std::cout << "AVR pin set to " << logic << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleImp()
|
||||||
|
{
|
||||||
|
a = 5;
|
||||||
|
//std::cout << "toggled AVR pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getImp()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_stuff()
|
||||||
|
{
|
||||||
|
a = 10;
|
||||||
|
//std::cout << "AVR specific stuff" << std::endl;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
|
||||||
|
int a;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void foo(T& base)
|
||||||
|
{
|
||||||
|
base.set(true);
|
||||||
|
base.set(false);
|
||||||
|
base.toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void baa(PinBase<T>& pin)
|
||||||
|
{
|
||||||
|
pin.toggle();
|
||||||
|
//foo(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
template <typename T>
|
||||||
|
struct Driver
|
||||||
|
{
|
||||||
|
Driver(PinBase<T>& pin) : pin(pin)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void doSomething()
|
||||||
|
{
|
||||||
|
pin.toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
PinBase<T> pin;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct Driver
|
||||||
|
{
|
||||||
|
Driver(IPin& pin) : pin(pin)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void doSomething()
|
||||||
|
{
|
||||||
|
pin.toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
IPin& pin;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
//STM32_Pin pin1;
|
||||||
|
AVR_Pin pin2;
|
||||||
|
|
||||||
|
|
||||||
|
//pin1.STM32_stuff();
|
||||||
|
|
||||||
|
pin2.avr_stuff();
|
||||||
|
#if 0
|
||||||
|
foo(pin1);
|
||||||
|
foo(pin2);
|
||||||
|
|
||||||
|
baa(pin1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
Driver drv(pin2);
|
||||||
|
|
||||||
|
drv.doSomething();
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
Curiously recurring template pattern (CRTP)
|
||||||
|
|
||||||
|
https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
|
||||||
|
|
||||||
|
https://www.youtube.com/watch?v=7-nHdQjSRe0&t=480s
|
@ -0,0 +1,29 @@
|
|||||||
|
cpp_src = $(wildcard *.cpp)
|
||||||
|
cpp_src += $(wildcard ./utils/*.cpp)
|
||||||
|
cpp_src += $(wildcard ./driver/*.cpp)
|
||||||
|
|
||||||
|
cpp_obj = $(cpp_src:.cpp=.o)
|
||||||
|
c_obj = $(c_src:.c=.o)
|
||||||
|
CC = g++
|
||||||
|
CFLAGS = -Wall -pedantic -li2c
|
||||||
|
LDFLAGS = -lpthread
|
||||||
|
EXEC = runtest
|
||||||
|
|
||||||
|
|
||||||
|
all : $(EXEC)
|
||||||
|
|
||||||
|
$(EXEC): $(cpp_obj) $(c_obj)
|
||||||
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
debug : $(EXEC)
|
||||||
|
|
||||||
|
$(EXEC): $(cpp_obj) $(c_obj)
|
||||||
|
$(CC) -g -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
||||||
|
|
||||||
|
cleanall:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
@ -0,0 +1,77 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
pthread_mutex_t print_mtx;
|
||||||
|
|
||||||
|
class IThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
virtual void* _run() = 0;
|
||||||
|
|
||||||
|
static void* _staticRun(void* context)
|
||||||
|
{
|
||||||
|
return static_cast<IThread*>(context)->_run();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void printer(std::string a)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&print_mtx);
|
||||||
|
|
||||||
|
std::cout << a << std::endl;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&print_mtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* foo(void* arg)
|
||||||
|
{
|
||||||
|
unsigned int i = 100;
|
||||||
|
for(;i > 0; i--){
|
||||||
|
std::string a = "foo cnt: ";
|
||||||
|
a += std::to_string(i);
|
||||||
|
printer(a);
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void* baa(void* arg)
|
||||||
|
{
|
||||||
|
unsigned int i = 5;
|
||||||
|
|
||||||
|
for(;i > 0; i--){
|
||||||
|
std::string a = "baa cnt: ";
|
||||||
|
a += std::to_string(i);
|
||||||
|
printer(a);
|
||||||
|
sleep(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
pthread_t foo_th, baa_th;
|
||||||
|
|
||||||
|
|
||||||
|
pthread_mutex_init(&print_mtx, NULL);
|
||||||
|
|
||||||
|
pthread_create(&foo_th, NULL, foo, NULL);
|
||||||
|
pthread_create(&baa_th, NULL, baa, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
pthread_join(foo_th, NULL);
|
||||||
|
pthread_join(baa_th, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"*.tcc": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"typeinfo": "cpp"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
cpp_src = $(wildcard *.cpp)
|
||||||
|
cpp_src += $(wildcard ./utils/*.cpp)
|
||||||
|
cpp_src += $(wildcard ./driver/*.cpp)
|
||||||
|
|
||||||
|
cpp_obj = $(cpp_src:.cpp=.o)
|
||||||
|
c_obj = $(c_src:.c=.o)
|
||||||
|
CC = g++
|
||||||
|
CFLAGS = -Wall -pedantic -li2c
|
||||||
|
LDFLAGS =
|
||||||
|
EXEC = runtest
|
||||||
|
|
||||||
|
|
||||||
|
all : $(EXEC)
|
||||||
|
|
||||||
|
$(EXEC): $(cpp_obj) $(c_obj)
|
||||||
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
||||||
|
|
||||||
|
cleanall:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
@ -1,14 +1,69 @@
|
|||||||
#include "device.hpp"
|
#include "device.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
Device::Device()
|
Device::Device() :
|
||||||
|
reg_control(0x00)
|
||||||
{
|
{
|
||||||
Reg_Control.POWER_DEV = Reg_Control::POWER_DEV::TURN_OFF;
|
|
||||||
Reg_Control.SPEED = Reg_Control::SPEED::STAND_STILL;
|
|
||||||
|
|
||||||
std::cout << Reg_Control.raw;
|
std::cout << "Device::Device()" << std::endl;
|
||||||
|
std::cout << +reg_control.raw << std::endl;
|
||||||
|
|
||||||
|
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_OFF;
|
||||||
|
reg_control.bits.SPEED = Reg_Control::SPEED::STAND_STILL;
|
||||||
|
|
||||||
|
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
|
||||||
|
std::cout << "SPEED = " <<+reg_control.bits.SPEED << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::doSomething()
|
void Device::doSomething()
|
||||||
{
|
{
|
||||||
|
std::cout << "Device::doSomething()" << std::endl;
|
||||||
|
|
||||||
|
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
|
||||||
|
reg_control.bits.SPEED = Reg_Control::SPEED::FAST;
|
||||||
|
|
||||||
|
if(reg_control.bits.POWER_DEV == Reg_Control::POWER_DEV::TURN_ON){
|
||||||
|
std::cout << "device turned on!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
|
||||||
|
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
|
||||||
|
|
||||||
|
std::cout << +reg_control << std::endl;
|
||||||
|
|
||||||
|
reg_control = 0;
|
||||||
|
|
||||||
|
std::cout << +reg_control << std::endl;
|
||||||
|
|
||||||
|
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
|
||||||
|
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
|
||||||
|
|
||||||
|
//reg_control.bits.SPEED = Reg_Control::SPEED::FAST;
|
||||||
|
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
|
||||||
|
|
||||||
|
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
|
||||||
|
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::status()
|
||||||
|
{
|
||||||
|
// imitating read hardware register (for example reading from device via SPI or i2c)
|
||||||
|
reg_motorStatus = 0xFE;
|
||||||
|
|
||||||
|
if(reg_motorStatus.bits.POWER == Reg_MotorStatus::POWER::ON) {
|
||||||
|
std::cout << "Motor is Powered ON!" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Motor is Powered OFF!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// will throw error because this bitfield is set const!
|
||||||
|
//reg_motorStatus.bits.STATUS = Reg_MotorStatus::STATUS::STANDSTILL;
|
||||||
|
|
||||||
|
std::cout << +reg_motorStatus.bits.POWER << std::endl;
|
||||||
|
|
||||||
|
std::cout << "Motor Status : " << +reg_motorStatus.bits.STATUS << std::endl;
|
||||||
}
|
}
|
@ -1,9 +1,57 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "mcp4725/mcp4725.hpp"
|
#include "./driver/device.hpp"
|
||||||
|
#include "./utils/BitField.hpp"
|
||||||
|
|
||||||
|
#ifdef SIMPLE_TEST
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
std::cout << "test" << std::endl;
|
||||||
|
|
||||||
|
BitField<uint8_t, 1, 2> bitfield_0;
|
||||||
|
BitField<uint8_t, 5, 2> bitfield_1;
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "testing bitfield 0" << std::endl;
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < 10; i++) {
|
||||||
|
|
||||||
|
bitfield_0 = i;
|
||||||
|
std::cout << static_cast<uint32_t>(bitfield_0()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "testing bitfield 1" << std::endl;
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < 10; i++) {
|
||||||
|
|
||||||
|
bitfield_1 = i;
|
||||||
|
std::cout << static_cast<uint32_t>(bitfield_1()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Device dev();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
std::cout << "test" << std::endl;
|
||||||
|
|
||||||
|
//std::cout << std::hex << ((1ULL << 2)-1) << std::endl;
|
||||||
|
std::cout << 1ULL << std::endl;
|
||||||
|
|
||||||
|
Device dev;
|
||||||
|
|
||||||
|
//dev.doSomething();
|
||||||
|
|
||||||
|
dev.status();
|
||||||
|
|
||||||
|
//dev.doSomething();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
#include "mcp4725.hpp"
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
MCP4725::MCP4725(pwrd_md power_down_mode,
|
|
||||||
i2c_addr address,
|
|
||||||
I2C* i2c) :
|
|
||||||
power_down_mode(power_down_mode),
|
|
||||||
address(address),
|
|
||||||
i2c(i2c),
|
|
||||||
dac_value(0),
|
|
||||||
eeprom_value(0)
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
uint8_t temp[6];
|
|
||||||
|
|
||||||
temp[0] = cmd_write_dac_and_eeprom | (power_down_mode << 1);
|
|
||||||
temp[1] = static_cast<uint8_t>(dac_value >> 4);
|
|
||||||
temp[2] = static_cast<uint8_t>(dac_value << 4);
|
|
||||||
temp[3] = temp[0];
|
|
||||||
temp[4] = temp[1];
|
|
||||||
temp[5] = temp[2];
|
|
||||||
|
|
||||||
//i2c_write(address, temp,6);
|
|
||||||
}
|
|
||||||
|
|
||||||
MCP4725::MCP4725(i2c_addr address,
|
|
||||||
I2C* i2c) :
|
|
||||||
power_down_mode(pwrd_md::normal),
|
|
||||||
address(address),
|
|
||||||
i2c(i2c),
|
|
||||||
dac_value(0),
|
|
||||||
eeprom_value(0)
|
|
||||||
|
|
||||||
{
|
|
||||||
uint8_t temp[6];
|
|
||||||
|
|
||||||
temp[0] = cmd_write_dac_and_eeprom | (power_down_mode << 1);
|
|
||||||
temp[1] = static_cast<uint8_t>(dac_value >> 4);
|
|
||||||
temp[2] = static_cast<uint8_t>(dac_value << 4);
|
|
||||||
temp[3] = temp[0];
|
|
||||||
temp[4] = temp[1];
|
|
||||||
temp[5] = temp[2];
|
|
||||||
|
|
||||||
//i2c_write(address, temp, 6);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MCP4725::MCP4725()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MCP4725::MCP4725(I2C* i2c) :
|
|
||||||
power_down_mode(pwrd_md::normal),
|
|
||||||
address(addr_0x60),
|
|
||||||
i2c(i2c),
|
|
||||||
dac_value(0),
|
|
||||||
eeprom_value(0)
|
|
||||||
|
|
||||||
{
|
|
||||||
uint8_t temp[6];
|
|
||||||
|
|
||||||
temp[0] = cmd_write_dac_and_eeprom | (power_down_mode << 1);
|
|
||||||
temp[1] = static_cast<uint8_t>(dac_value >> 4);
|
|
||||||
temp[2] = static_cast<uint8_t>(dac_value << 4);
|
|
||||||
temp[3] = temp[0];
|
|
||||||
temp[4] = temp[1];
|
|
||||||
temp[5] = temp[2];
|
|
||||||
|
|
||||||
i2c->writeBuffer(address, temp, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
//MCP4725::~MCP4725()
|
|
||||||
//{
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
void MCP4725::operator=(uint16_t dac_value)
|
|
||||||
{
|
|
||||||
uint8_t temp[3];
|
|
||||||
this->dac_value = dac_value;
|
|
||||||
|
|
||||||
temp[0] = cmd_write_dac | (power_down_mode << 1);
|
|
||||||
temp[1] = static_cast<uint8_t>(dac_value >> 4);
|
|
||||||
temp[2] = static_cast<uint8_t>(dac_value << 4);
|
|
||||||
|
|
||||||
|
|
||||||
i2c->writeBuffer(address, temp, 3);
|
|
||||||
|
|
||||||
//i2c_write(address, temp, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void MCP4725::operator==(uint16_t dac_and_eeprom_value)
|
|
||||||
{
|
|
||||||
uint8_t temp[6];
|
|
||||||
dac_value = dac_and_eeprom_value;
|
|
||||||
eeprom_value = dac_value;
|
|
||||||
|
|
||||||
temp[0] = cmd_write_dac_and_eeprom | (power_down_mode << 1);
|
|
||||||
temp[1] = static_cast<uint8_t>(dac_and_eeprom_value >> 4);
|
|
||||||
temp[2] = static_cast<uint8_t>(dac_and_eeprom_value << 4);
|
|
||||||
temp[3] = temp[0];
|
|
||||||
temp[4] = temp[1];
|
|
||||||
temp[5] = temp[2];
|
|
||||||
|
|
||||||
i2c->writeBuffer(address, temp, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
void MCP4725::write_dac(uint16_t dac_value)
|
|
||||||
{
|
|
||||||
&this = dac_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MCP4725::write_dac_and_eeprom(uint16_t dac_and_eeprom_value)
|
|
||||||
{
|
|
||||||
&this == dac_and_eeprom_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,100 +0,0 @@
|
|||||||
#ifndef _MCP4725_HPP_
|
|
||||||
#define _MCP4725_HPP_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <functional>
|
|
||||||
#include "../../communication/i2c/i2c.hpp"
|
|
||||||
|
|
||||||
class MCP4725
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//typedef std::function<void(uint8_t,uint8_t*,uint8_t)> i2c_write_n_t;
|
|
||||||
//typedef std::function<void(const uint8_t&,const uint8_t*,const uint8_t&)> i2c_write_n_t;
|
|
||||||
//typedef void(*i2c_write_n_t)(const uint8_t&, const uint8_t*, const uint8_t&);
|
|
||||||
|
|
||||||
//typedef std::function<void(int)>i2c_write_n_t;
|
|
||||||
|
|
||||||
// address list
|
|
||||||
enum i2c_addr
|
|
||||||
{
|
|
||||||
addr_0x60 = 0b01100000,
|
|
||||||
addr_0x61 = addr_0x60 + 1,
|
|
||||||
addr_0x62 = addr_0x60 + 2,
|
|
||||||
addr_0x63 = addr_0x60 + 3,
|
|
||||||
addr_0x64 = addr_0x60 + 4,
|
|
||||||
addr_0x65 = addr_0x60 + 5,
|
|
||||||
addr_0x66 = addr_0x60 + 6,
|
|
||||||
addr_0x67 = addr_0x60 + 7
|
|
||||||
};
|
|
||||||
|
|
||||||
// power down impedance modes
|
|
||||||
enum pwrd_md
|
|
||||||
{
|
|
||||||
normal = 0x04,
|
|
||||||
ohm_1k = 0x01,
|
|
||||||
ohm_100k = 0x02,
|
|
||||||
ohm_500k = 0x03
|
|
||||||
};
|
|
||||||
|
|
||||||
//using std::functional<uint8_t(uint8_t, uint8_t)> i2c_read_n_t;
|
|
||||||
|
|
||||||
//using i2c_write_n_t = std::functional<void(uint8_t, uint8_t*,uint8_t)>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructor of mcp4725 dac
|
|
||||||
*
|
|
||||||
* @param power_down_mode pwrd_md power down mode
|
|
||||||
* @param address i2c_addr i2c address of the dac
|
|
||||||
* @param i2c_write i2c_write_n_t callback for i2c writ
|
|
||||||
*/
|
|
||||||
#if 0
|
|
||||||
MCP4725(pwrd_md power_down_mode,
|
|
||||||
i2c_addr address,
|
|
||||||
I2C* i2c);
|
|
||||||
|
|
||||||
MCP4725(i2c_addr address,
|
|
||||||
I2C* i2c);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MCP4725();
|
|
||||||
MCP4725(I2C* i2c);
|
|
||||||
|
|
||||||
// ~MCP4725();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void operator=(uint16_t dac_value);
|
|
||||||
|
|
||||||
void operator==(uint16_t dac_and_eeprom_value);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void write_dac_and_eeprom(uint16_t value);
|
|
||||||
|
|
||||||
void set_powerdown_impedance(pwrd_md mode);
|
|
||||||
|
|
||||||
i2c_addr get_i2c_addr();
|
|
||||||
#endif
|
|
||||||
//void set_power
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
enum commands_t
|
|
||||||
{
|
|
||||||
cmd_fast_mode = 0x00,
|
|
||||||
cmd_write_dac = 0x40,
|
|
||||||
cmd_write_dac_and_eeprom = 0x60
|
|
||||||
};
|
|
||||||
|
|
||||||
I2C* i2c;
|
|
||||||
|
|
||||||
i2c_addr address;
|
|
||||||
pwrd_md power_down_mode;
|
|
||||||
//i2c_write_n_t i2c_write;
|
|
||||||
uint16_t dac_value;
|
|
||||||
uint16_t eeprom_value;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _MCP4725_HPP_
|
|
@ -0,0 +1,126 @@
|
|||||||
|
// Example program
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Template class for portable Bitfields
|
||||||
|
*
|
||||||
|
* @tparam T type of variable in which the bitfield resides
|
||||||
|
* @tparam START bit index starting from LSB where the bitfield starts
|
||||||
|
* @tparam SIZE number of bits
|
||||||
|
*/
|
||||||
|
template<typename T, uint8_t START, uint8_t SIZE>
|
||||||
|
struct BitField
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Construct a new Bit Field object
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BitField()
|
||||||
|
{
|
||||||
|
static_assert(SIZE != 0, "Bitfield SIZE must be > 0!");
|
||||||
|
static_assert(START < sizeof(T) * 8, "START exceeds number of bits of the chosen typename T!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief assignment operator
|
||||||
|
*
|
||||||
|
* @param v value to be written in the bitfield
|
||||||
|
* @return BitField&
|
||||||
|
*/
|
||||||
|
BitField& operator =(T v)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
_raw = ((v & ((1ULL << SIZE)-1)) << START);
|
||||||
|
return *this;
|
||||||
|
#else
|
||||||
|
//_raw & ~(((1ULL << SIZE)-1) << START);
|
||||||
|
|
||||||
|
// use bit band alias if system permits
|
||||||
|
_raw = ((v & ((1ULL << SIZE)-1)) << START) | (_raw & ~(((1ULL << SIZE)-1) << START));
|
||||||
|
return *this;
|
||||||
|
//#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief return the value inside the bitfield
|
||||||
|
*
|
||||||
|
* @return T
|
||||||
|
*/
|
||||||
|
operator T() const
|
||||||
|
{
|
||||||
|
return _raw >> START;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief return the raw value
|
||||||
|
*
|
||||||
|
* @return T
|
||||||
|
*/
|
||||||
|
T operator ()() const
|
||||||
|
{
|
||||||
|
return _raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T _raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
union Reg_Control
|
||||||
|
{
|
||||||
|
// bit 4
|
||||||
|
struct POWER_DEV{
|
||||||
|
typedef BitField<uint8_t, 7, 1> Bits;
|
||||||
|
enum{TURN_OFF = 0, TURN_ON = 1};
|
||||||
|
};
|
||||||
|
// bits 2-3
|
||||||
|
struct SPEED{
|
||||||
|
typedef BitField<uint8_t, 0, 2> Bits;
|
||||||
|
enum{STAND_STILL = 0,
|
||||||
|
SLOW = 1,
|
||||||
|
NORMAL = 2,
|
||||||
|
FAST = 3};
|
||||||
|
};
|
||||||
|
union Bits{
|
||||||
|
Reg_Control::POWER_DEV::Bits POWER_DEV;
|
||||||
|
Reg_Control::SPEED::Bits SPEED;
|
||||||
|
} bits;
|
||||||
|
// raw value. all bitfields will be "unified" here ;)
|
||||||
|
uint8_t raw;
|
||||||
|
// union Ctor with default value set to 0x00
|
||||||
|
Reg_Control(uint8_t v = 0x00) : raw(v) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Reg_Control reg;
|
||||||
|
|
||||||
|
//reg.bits.SPEED = Reg_Control::SPEED::FAST;
|
||||||
|
reg.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << +reg.raw << std::endl;
|
||||||
|
|
||||||
|
reg.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_OFF;
|
||||||
|
|
||||||
|
std::cout << +reg.raw << std::endl;
|
||||||
|
|
||||||
|
reg.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
|
||||||
|
reg.bits.SPEED = Reg_Control::SPEED::SLOW;
|
||||||
|
|
||||||
|
std::cout << +reg.raw << std::endl;
|
||||||
|
|
||||||
|
reg.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_OFF;
|
||||||
|
reg.bits.SPEED = Reg_Control::SPEED::FAST;
|
||||||
|
|
||||||
|
std::cout << +reg.raw << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Binary file not shown.
@ -0,0 +1,24 @@
|
|||||||
|
cpp_src = $(wildcard *.cpp)
|
||||||
|
cpp_src += $(wildcard ./utils/*.cpp)
|
||||||
|
cpp_src += $(wildcard ./driver/*.cpp)
|
||||||
|
|
||||||
|
cpp_obj = $(cpp_src:.cpp=.o)
|
||||||
|
c_obj = $(c_src:.c=.o)
|
||||||
|
CC = g++
|
||||||
|
CFLAGS = -Wall -pedantic -li2c
|
||||||
|
LDFLAGS =
|
||||||
|
EXEC = runtest
|
||||||
|
|
||||||
|
|
||||||
|
all : $(EXEC)
|
||||||
|
|
||||||
|
$(EXEC): $(cpp_obj) $(c_obj)
|
||||||
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
||||||
|
|
||||||
|
cleanall:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
@ -0,0 +1,105 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "utils/BitField.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
union GPIO_MODER
|
||||||
|
{
|
||||||
|
struct MODER{
|
||||||
|
enum{
|
||||||
|
INPUT_MODE,
|
||||||
|
OUTPUT,
|
||||||
|
ALT_FUNCTION,
|
||||||
|
ANALOG
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MODER_0 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 0, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_1 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 2, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_2 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 4, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_3 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 6, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_4 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 8, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_5 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 10, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_6 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 12, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_7 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 14, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_8 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 16, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_9 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 18, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_10 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 20, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_11 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 22, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_12 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 24, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_13 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 26, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_14 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 28, 2> Bits;
|
||||||
|
};
|
||||||
|
struct MODER_15 : public MODER{
|
||||||
|
typedef BitField<uint32_t, 30, 2> Bits;
|
||||||
|
};
|
||||||
|
union{
|
||||||
|
GPIO_MODER::MODER_0::Bits MODER_0;
|
||||||
|
GPIO_MODER::MODER_1::Bits MODER_1;
|
||||||
|
GPIO_MODER::MODER_2::Bits MODER_2;
|
||||||
|
GPIO_MODER::MODER_3::Bits MODER_3;
|
||||||
|
GPIO_MODER::MODER_4::Bits MODER_4;
|
||||||
|
GPIO_MODER::MODER_5::Bits MODER_5;
|
||||||
|
GPIO_MODER::MODER_6::Bits MODER_6;
|
||||||
|
GPIO_MODER::MODER_7::Bits MODER_7;
|
||||||
|
GPIO_MODER::MODER_8::Bits MODER_8;
|
||||||
|
GPIO_MODER::MODER_9::Bits MODER_9;
|
||||||
|
GPIO_MODER::MODER_10::Bits MODER_10;
|
||||||
|
GPIO_MODER::MODER_11::Bits MODER_11;
|
||||||
|
GPIO_MODER::MODER_12::Bits MODER_12;
|
||||||
|
GPIO_MODER::MODER_13::Bits MODER_13;
|
||||||
|
GPIO_MODER::MODER_14::Bits MODER_14;
|
||||||
|
GPIO_MODER::MODER_15::Bits MODER_15;
|
||||||
|
}bits;
|
||||||
|
|
||||||
|
uint32_t raw;
|
||||||
|
|
||||||
|
GPIO_MODER(uint32_t v = 0x00) : raw(v) {}
|
||||||
|
operator uint32_t() {return raw;}
|
||||||
|
void operator = (uint32_t v) {raw = v;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
GPIO_MODER MODER_A;
|
||||||
|
|
||||||
|
// for reference use the STM32F0 reference manualchapter GPIO
|
||||||
|
|
||||||
|
MODER_A.bits.MODER_0 = GPIO_MODER::MODER_0::OUTPUT;
|
||||||
|
MODER_A.bits.MODER_5 = GPIO_MODER::MODER_5::ALT_FUNCTION;
|
||||||
|
|
||||||
|
std::cout << +MODER_A << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Binary file not shown.
@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* @file BitField.h
|
||||||
|
* @author Edwin Koch (eddyed.k@gmail.com)
|
||||||
|
* @brief
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2020-12-19
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2020
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Based on:
|
||||||
|
// https://www.youtube.com/watch?v=TYqbgvHfxjM
|
||||||
|
// https://stackoverflow.com/questions/31726191/is-there-a-portable-alternative-to-c-bitfields
|
||||||
|
// https://stackoverflow.com/questions/1392059/algorithm-to-generate-bit-mask
|
||||||
|
|
||||||
|
#ifndef _BITFIELDS_HPP_
|
||||||
|
#define _BITFIELDS_HPP_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Template class for portable Bitfields
|
||||||
|
*
|
||||||
|
* @tparam T type of variable in which the bitfield resides
|
||||||
|
* @tparam START bit index starting from LSB where the bitfield starts
|
||||||
|
* @tparam SIZE number of bits
|
||||||
|
*/
|
||||||
|
template<typename T, uint8_t START, uint8_t SIZE>
|
||||||
|
struct BitField
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Construct a new Bit Field object
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BitField()
|
||||||
|
{
|
||||||
|
static_assert(SIZE != 0, "Bitfield SIZE must be > 0!");
|
||||||
|
static_assert(START < sizeof(T) * 8, "START exceeds number of bits of the chosen typename T!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief assignment operator
|
||||||
|
*
|
||||||
|
* @param v value to be written in the bitfield
|
||||||
|
* @return BitField&
|
||||||
|
*/
|
||||||
|
BitField& operator =(T v)
|
||||||
|
{
|
||||||
|
// use bit band alias if system permits
|
||||||
|
_raw = ((v & ((1ULL << SIZE)-1)) << START) | (_raw & ~(((1ULL << SIZE)-1) << START));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief return the value inside the bitfield
|
||||||
|
*
|
||||||
|
* @return T
|
||||||
|
*/
|
||||||
|
operator T() const
|
||||||
|
{
|
||||||
|
return (_raw >> START) & ((1ULL << SIZE) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief return the raw value
|
||||||
|
*
|
||||||
|
* @return T
|
||||||
|
*/
|
||||||
|
T operator ()() const
|
||||||
|
{
|
||||||
|
return (_raw >> START) & ((1ULL << SIZE) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T _raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _BITFIELDS_HPP_
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// counter.c
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2019
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "counter.h"
|
||||||
|
|
||||||
|
static int countValue;
|
||||||
|
|
||||||
|
void cnt_init(int val)
|
||||||
|
{
|
||||||
|
countValue = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnt_count(int step)
|
||||||
|
{
|
||||||
|
countValue += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnt_getCounter()
|
||||||
|
{
|
||||||
|
return countValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cnt_setCounter(int val)
|
||||||
|
{
|
||||||
|
countValue = val;
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// counter.h
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2019
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTER_H__
|
||||||
|
#define COUNTER_H__
|
||||||
|
|
||||||
|
void cnt_init(int val);
|
||||||
|
// initializes counter to val
|
||||||
|
|
||||||
|
void cnt_count(int step);
|
||||||
|
// counts the counter up (step>0) or down (step<0) by step
|
||||||
|
|
||||||
|
int cnt_getCounter();
|
||||||
|
// returns the counter value
|
||||||
|
|
||||||
|
void cnt_setCounter(int val);
|
||||||
|
// sets the counter to val
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// counterCtrl.c
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2019
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "counterCtrl.h"
|
||||||
|
#include "counter.h"
|
||||||
|
|
||||||
|
typedef enum {idleState, // idle state
|
||||||
|
countUpState, // counting up at each count event
|
||||||
|
countDownState} // counting down at each count event
|
||||||
|
State;
|
||||||
|
|
||||||
|
static State currentState = idleState; // holds the current state of the FSM
|
||||||
|
|
||||||
|
void cnt_ctrlInit(int initValue)
|
||||||
|
{
|
||||||
|
currentState = idleState;
|
||||||
|
cnt_init(initValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cnt_ctrlProcess(cnt_Event e)
|
||||||
|
{
|
||||||
|
switch (currentState)
|
||||||
|
{
|
||||||
|
case idleState:
|
||||||
|
printf("State: idleState\n");
|
||||||
|
if (cnt_evUp == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
printf("State: idleState, counter = %d\n", cnt_getCounter());
|
||||||
|
// state transition
|
||||||
|
printf("Changing to State: countUpState\n");
|
||||||
|
currentState = countUpState;
|
||||||
|
}
|
||||||
|
else if (cnt_evDown == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
printf("State: idleState, counter = %d\n", cnt_getCounter());
|
||||||
|
// state transition
|
||||||
|
printf("Changing to State: countDownState\n");
|
||||||
|
currentState = countDownState;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case countUpState:
|
||||||
|
printf("State: countUpState\n");
|
||||||
|
if (cnt_evCount == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
cnt_count(1);
|
||||||
|
printf("State: countUpState, counter = %d\n", cnt_getCounter());
|
||||||
|
// state transition
|
||||||
|
}
|
||||||
|
else if (cnt_evStop == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
// state transition
|
||||||
|
printf("Changing to State: idleState\n");
|
||||||
|
currentState = idleState;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case countDownState:
|
||||||
|
printf("State: countDownState\n");
|
||||||
|
if (cnt_evCount == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
cnt_count(-1);
|
||||||
|
printf("State: countDownState, counter = %d\n", cnt_getCounter());
|
||||||
|
// state transition
|
||||||
|
}
|
||||||
|
else if (cnt_evStop == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
// state transition
|
||||||
|
printf("Changing to State: idleState\n");
|
||||||
|
currentState = idleState;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// counterCtrl.h
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2019
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTERCTRL_H__
|
||||||
|
#define COUNTERCTRL_H__
|
||||||
|
|
||||||
|
typedef enum {cnt_evUp, // count upwards
|
||||||
|
cnt_evDown, // count downwards
|
||||||
|
cnt_evCount, // count (up or down)
|
||||||
|
cnt_evStop} // stop counting
|
||||||
|
cnt_Event;
|
||||||
|
|
||||||
|
void cnt_ctrlInit(int initValue);
|
||||||
|
// initializes counter FSM
|
||||||
|
|
||||||
|
void cnt_ctrlProcess(cnt_Event e);
|
||||||
|
// changes the state of the FSM based on the event 'e'
|
||||||
|
// starts the actions
|
||||||
|
|
||||||
|
#endif
|
Binary file not shown.
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// counterTest.c
|
||||||
|
//
|
||||||
|
// Test program for the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2019
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "counterCtrl.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char answer;
|
||||||
|
|
||||||
|
cnt_ctrlInit(0);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
printf("\n-------------------------------------------\n");
|
||||||
|
printf(" u Count up\n");
|
||||||
|
printf(" d Count down\n");
|
||||||
|
printf(" c Count\n");
|
||||||
|
printf(" s Stop counting\n");
|
||||||
|
printf(" q Quit\n");
|
||||||
|
|
||||||
|
printf("\nPlease press key: ");
|
||||||
|
scanf("%c", &answer);
|
||||||
|
getchar(); // nach scanf() ist noch ein '\n' im Inputbuffer: auslesen und wegwerfen
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
switch (answer)
|
||||||
|
{
|
||||||
|
case 'u':
|
||||||
|
cnt_ctrlProcess(cnt_evUp);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
cnt_ctrlProcess(cnt_evDown);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
cnt_ctrlProcess(cnt_evCount);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
cnt_ctrlProcess(cnt_evStop);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (answer != 'q');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// counterTest.c
|
||||||
|
//
|
||||||
|
// Test program for the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2014
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "counterCtrl.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char answer;
|
||||||
|
|
||||||
|
cntCtrlInit(0);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
printf("\n-------------------------------------------\n");
|
||||||
|
printf(" u Count up\n");
|
||||||
|
printf(" d Count down\n");
|
||||||
|
printf(" c Count\n");
|
||||||
|
printf(" s Stop counting\n");
|
||||||
|
printf(" q Quit\n");
|
||||||
|
|
||||||
|
printf("\nPlease press key: ");
|
||||||
|
scanf("%c", &answer);
|
||||||
|
// getchar(); // nach scanf() ist noch ein '\n' im Inputbuffer: auslesen und wegwerfen
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
switch (answer)
|
||||||
|
{
|
||||||
|
case 'u':
|
||||||
|
cntCtrlProcess(cntEvUp);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
cntCtrlProcess(cntEvDown);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
cntCtrlProcess(cntEvCount);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
cntCtrlProcess(cntEvStop);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (answer != 'q');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
#
|
||||||
|
# Makefile fuer Counter-Programm
|
||||||
|
# File: makefile
|
||||||
|
# Reto Bonderer, 24.11.2010
|
||||||
|
#
|
||||||
|
CC = gcc
|
||||||
|
LINK = gcc
|
||||||
|
# '-pedantic' sorgt dafuer, dass gcc streng arbeitet
|
||||||
|
#CFLAGS = -c -pedantic
|
||||||
|
#LFLAGS = -pedantic
|
||||||
|
CFLAGS = -c -Wall
|
||||||
|
LFLAGS = -Wall
|
||||||
|
OBJS = counter.o counterCtrl.o counterTest.o
|
||||||
|
EXE = counterTest
|
||||||
|
|
||||||
|
$(EXE): $(OBJS)
|
||||||
|
$(LINK) $(LFLAGS) -o $(EXE) $(OBJS)
|
||||||
|
|
||||||
|
counterTest.o: counterTest.c counterCtrl.h
|
||||||
|
$(CC) $(CFLAGS) counterTest.c
|
||||||
|
|
||||||
|
counter.o: counter.c counter.h
|
||||||
|
$(CC) $(CFLAGS) counter.c
|
||||||
|
|
||||||
|
counterCtrl.o: counterCtrl.c counterCtrl.h counter.h
|
||||||
|
$(CC) $(CFLAGS) counterCtrl.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(EXE) $(OBJS)
|
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Counter.cpp
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Counter.h"
|
||||||
|
|
||||||
|
Counter::Counter(int val): countValue(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::count(int step)
|
||||||
|
{
|
||||||
|
countValue += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Counter::getCounter() const
|
||||||
|
{
|
||||||
|
return countValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::setCounter(int val)
|
||||||
|
{
|
||||||
|
countValue = val;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Counter.h
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTER_H__
|
||||||
|
#define COUNTER_H__
|
||||||
|
|
||||||
|
class Counter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Counter(int val = 0);
|
||||||
|
|
||||||
|
void count(int step);
|
||||||
|
// counts the counter up (step>0) or down (step<0) by step
|
||||||
|
|
||||||
|
int getCounter() const;
|
||||||
|
// returns the counter value
|
||||||
|
|
||||||
|
void setCounter(int val);
|
||||||
|
// sets the counter to val
|
||||||
|
private:
|
||||||
|
int countValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,84 @@
|
|||||||
|
//
|
||||||
|
// CounterCtrl.cpp
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "CounterCtrl.h"
|
||||||
|
#include "Counter.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
CounterCtrl::CounterCtrl(int initValue) :
|
||||||
|
currentState(idleState),
|
||||||
|
myCounter(initValue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::process(Event e)
|
||||||
|
{
|
||||||
|
switch (currentState)
|
||||||
|
{
|
||||||
|
case idleState:
|
||||||
|
cout << "State: idleState" << endl;
|
||||||
|
if (evUp == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
// state transition
|
||||||
|
cout << "Changing to State: countUpState" << endl;
|
||||||
|
currentState = countUpState;
|
||||||
|
}
|
||||||
|
else if (evDown == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
// state transition
|
||||||
|
cout << "Changing to State: countDownState" << endl;
|
||||||
|
currentState = countDownState;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case countUpState:
|
||||||
|
cout << "State: countUpState" << endl;
|
||||||
|
if (evCount == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
myCounter.count(1);
|
||||||
|
cout << "State: countUpState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
// state transition
|
||||||
|
}
|
||||||
|
else if (evStop == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
// state transition
|
||||||
|
cout << "Changing to State: idleState" << endl;
|
||||||
|
currentState = idleState;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case countDownState:
|
||||||
|
cout << "State: countDownState" << endl;
|
||||||
|
if (evCount == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
myCounter.count(-1);
|
||||||
|
cout << "State: countDownState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
// state transition
|
||||||
|
}
|
||||||
|
else if (evStop == e)
|
||||||
|
{
|
||||||
|
// actions
|
||||||
|
// state transition
|
||||||
|
cout << "Changing to State: idleState" << endl;
|
||||||
|
currentState = idleState;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// CounterCtrl.h
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTERCTRL_H__
|
||||||
|
#define COUNTERCTRL_H__
|
||||||
|
#include "Counter.h"
|
||||||
|
|
||||||
|
class CounterCtrl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Event{evUp, // count upwards
|
||||||
|
evDown, // count downwards
|
||||||
|
evCount, // count (up or down)
|
||||||
|
evStop}; // stop counting
|
||||||
|
CounterCtrl(int initValue = 0);
|
||||||
|
void process(Event e);
|
||||||
|
// changes the state of the FSM based on the event 'e'
|
||||||
|
// starts the actions
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum State{idleState, // idle state
|
||||||
|
countUpState, // counting up at each count event
|
||||||
|
countDownState}; // counting down at each count event
|
||||||
|
|
||||||
|
State currentState; // holds the current state of the FSM
|
||||||
|
Counter myCounter;
|
||||||
|
};
|
||||||
|
#endif
|
Binary file not shown.
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// counterTest.cpp
|
||||||
|
//
|
||||||
|
// Test program for the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "CounterCtrl.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char answer;
|
||||||
|
CounterCtrl myFsm(0); // initValue of counter == 0
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cout << endl << "-------------------------------------------" << endl;
|
||||||
|
cout << " u Count up" << endl;
|
||||||
|
cout << " d Count down" << endl;
|
||||||
|
cout << " c Count" << endl;
|
||||||
|
cout << " s Stop counting" << endl;
|
||||||
|
cout << " q Quit" << endl;
|
||||||
|
|
||||||
|
cout << endl << "Please press key: ";
|
||||||
|
cin >> answer;
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
switch (answer)
|
||||||
|
{
|
||||||
|
case 'u':
|
||||||
|
myFsm.process(CounterCtrl::evUp);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
myFsm.process(CounterCtrl::evDown);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
myFsm.process(CounterCtrl::evCount);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
myFsm.process(CounterCtrl::evStop);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (answer != 'q');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
@ -0,0 +1,26 @@
|
|||||||
|
#
|
||||||
|
# Makefile fuer Counter-Programm
|
||||||
|
# File: makefile
|
||||||
|
# Reto Bonderer, 23.10.2018
|
||||||
|
#
|
||||||
|
CC = g++
|
||||||
|
LINK = g++
|
||||||
|
CFLAGS = -c -Wall
|
||||||
|
LFLAGS = -Wall
|
||||||
|
OBJS = Counter.o CounterCtrl.o counterTest.o
|
||||||
|
EXE = counterTest
|
||||||
|
|
||||||
|
$(EXE): $(OBJS)
|
||||||
|
$(LINK) $(LFLAGS) -o $(EXE) $(OBJS)
|
||||||
|
|
||||||
|
counterTest.o: counterTest.cpp CounterCtrl.h
|
||||||
|
$(CC) $(CFLAGS) counterTest.cpp
|
||||||
|
|
||||||
|
Counter.o: Counter.cpp Counter.h
|
||||||
|
$(CC) $(CFLAGS) Counter.cpp
|
||||||
|
|
||||||
|
CounterCtrl.o: CounterCtrl.cpp CounterCtrl.h Counter.h
|
||||||
|
$(CC) $(CFLAGS) CounterCtrl.cpp
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(EXE) $(OBJS)
|
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Counter.cpp
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Counter.h"
|
||||||
|
|
||||||
|
Counter::Counter(int val): countValue(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::count(int step)
|
||||||
|
{
|
||||||
|
countValue += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Counter::getCounter() const
|
||||||
|
{
|
||||||
|
return countValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::setCounter(int val)
|
||||||
|
{
|
||||||
|
countValue = val;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Counter.h
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTER_H__
|
||||||
|
#define COUNTER_H__
|
||||||
|
|
||||||
|
class Counter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Counter(int val=0);
|
||||||
|
|
||||||
|
void count(int step);
|
||||||
|
// counts the counter up (step>0) or down (step<0) by step
|
||||||
|
|
||||||
|
int getCounter() const;
|
||||||
|
// returns the counter value
|
||||||
|
|
||||||
|
void setCounter(int val);
|
||||||
|
// sets the counter to val
|
||||||
|
private:
|
||||||
|
int countValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// CounterCtrl.cpp
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
// CounterCtrl is the Context class in the State pattern
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "CounterCtrl.h"
|
||||||
|
#include "CounterState.h"
|
||||||
|
|
||||||
|
CounterCtrl::CounterCtrl(int initValue):
|
||||||
|
entity(initValue),
|
||||||
|
pState(IdleState::getInstance()) // initial state
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::process(Event e)
|
||||||
|
{ // delegates all requests to CounterState
|
||||||
|
pState = pState->handle(entity, e);
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// CounterCtrl.h
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTERCTRL_H__
|
||||||
|
#define COUNTERCTRL_H__
|
||||||
|
#include "Counter.h"
|
||||||
|
|
||||||
|
class CounterState; // forward declaration
|
||||||
|
|
||||||
|
class CounterCtrl
|
||||||
|
// this is the 'Context' class of the State pattern
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Event{evUp, // count upwards
|
||||||
|
evDown, // count downwards
|
||||||
|
evCount, // count (up or down)
|
||||||
|
evStop}; // stop counting
|
||||||
|
CounterCtrl(int initValue = 0);
|
||||||
|
void process(Event e);
|
||||||
|
// changes the state of the FSM based on the event 'e'
|
||||||
|
|
||||||
|
private:
|
||||||
|
Counter entity;
|
||||||
|
CounterState* pState; // holds the current state
|
||||||
|
};
|
||||||
|
#endif
|
@ -0,0 +1,102 @@
|
|||||||
|
//
|
||||||
|
// CounterState.cpp
|
||||||
|
//
|
||||||
|
// implements all states of an up/down-Counter
|
||||||
|
// this file contains all classes of the state machine.
|
||||||
|
// it may make sense to have separate files for each state
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "CounterState.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
// class CounterState
|
||||||
|
CounterState* CounterState::changeState(Counter& entity, CounterState* pnewState)
|
||||||
|
{
|
||||||
|
return pnewState;
|
||||||
|
}
|
||||||
|
|
||||||
|
// class IdleState
|
||||||
|
IdleState IdleState::instance;
|
||||||
|
IdleState* IdleState::getInstance()
|
||||||
|
{
|
||||||
|
return &instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
CounterState* IdleState::handle(Counter& entity, CounterCtrl::Event e)
|
||||||
|
{
|
||||||
|
cout << "State: idleState" << endl;
|
||||||
|
if (CounterCtrl::evUp == e)
|
||||||
|
{
|
||||||
|
// transition actions
|
||||||
|
cout << "counter = " << entity.getCounter() << endl;
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, CountUpState::getInstance());
|
||||||
|
}
|
||||||
|
else if (CounterCtrl::evDown == e)
|
||||||
|
{
|
||||||
|
// transition actions
|
||||||
|
cout << "counter = " << entity.getCounter() << endl;
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, CountDownState::getInstance());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// class CountUpState
|
||||||
|
CountUpState CountUpState::instance;
|
||||||
|
CountUpState* CountUpState::getInstance()
|
||||||
|
{
|
||||||
|
return &instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
CounterState* CountUpState::handle(Counter& entity, CounterCtrl::Event e)
|
||||||
|
{
|
||||||
|
cout << "State: countUpState" << endl;
|
||||||
|
if (CounterCtrl::evCount == e)
|
||||||
|
{
|
||||||
|
// transition actions
|
||||||
|
entity.count(1);
|
||||||
|
cout << "counter = " << entity.getCounter() << endl;
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, CountUpState::getInstance());
|
||||||
|
}
|
||||||
|
else if (CounterCtrl::evStop == e)
|
||||||
|
{
|
||||||
|
// transition actions
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, IdleState::getInstance());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// class CountDownState
|
||||||
|
CountDownState CountDownState::instance;
|
||||||
|
CountDownState* CountDownState::getInstance()
|
||||||
|
{
|
||||||
|
return &instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
CounterState* CountDownState::handle(Counter& entity, CounterCtrl::Event e)
|
||||||
|
{
|
||||||
|
cout << "State: countDownState" << endl;
|
||||||
|
if (CounterCtrl::evCount == e)
|
||||||
|
{
|
||||||
|
// transition actions
|
||||||
|
entity.count(-1);
|
||||||
|
cout << "counter = " << entity.getCounter() << endl;
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, CountDownState::getInstance());
|
||||||
|
}
|
||||||
|
else if (CounterCtrl::evStop == e)
|
||||||
|
{
|
||||||
|
// transition actions
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, IdleState::getInstance());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// CounterState.h
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
// this file contains all classes of the state machine
|
||||||
|
// it may make sense to have separate files for each state
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, 21.10.2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTERSTATE_H__
|
||||||
|
#define COUNTERSTATE_H__
|
||||||
|
#include "CounterCtrl.h" // Events are defined here
|
||||||
|
|
||||||
|
class CounterState // abstract base class
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e) = 0;
|
||||||
|
// returns new state
|
||||||
|
protected: // only inherited classes may use these member functions
|
||||||
|
CounterState* changeState(Counter& entity, CounterState* pnewState);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IdleState : public CounterState // it's a singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static IdleState* getInstance();
|
||||||
|
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
|
||||||
|
private:
|
||||||
|
IdleState() {};
|
||||||
|
static IdleState instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CountUpState : public CounterState // it's a singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static CountUpState* getInstance();
|
||||||
|
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
|
||||||
|
private:
|
||||||
|
CountUpState() {};
|
||||||
|
static CountUpState instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CountDownState : public CounterState // it's a singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static CountDownState* getInstance();
|
||||||
|
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
|
||||||
|
private:
|
||||||
|
CountDownState() {};
|
||||||
|
static CountDownState instance;
|
||||||
|
};
|
||||||
|
#endif
|
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// counterTest.cpp
|
||||||
|
//
|
||||||
|
// Test program for the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "CounterCtrl.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char answer;
|
||||||
|
CounterCtrl myFsm;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cout << endl << "-------------------------------------------" << endl;
|
||||||
|
cout << " u Count up" << endl;
|
||||||
|
cout << " d Count down" << endl;
|
||||||
|
cout << " c Count" << endl;
|
||||||
|
cout << " s Stop counting" << endl;
|
||||||
|
cout << " q Quit" << endl;
|
||||||
|
|
||||||
|
cout << endl << "Please press key: ";
|
||||||
|
cin >> answer;
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
switch (answer)
|
||||||
|
{
|
||||||
|
case 'u':
|
||||||
|
myFsm.process(CounterCtrl::evUp);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
myFsm.process(CounterCtrl::evDown);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
myFsm.process(CounterCtrl::evCount);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
myFsm.process(CounterCtrl::evStop);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (answer != 'q');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
@ -0,0 +1,29 @@
|
|||||||
|
#
|
||||||
|
# Makefile fuer Counter-Programm
|
||||||
|
# File: makefile
|
||||||
|
# Reto Bonderer, 21.10.2017
|
||||||
|
#
|
||||||
|
CC = g++
|
||||||
|
LINK = g++
|
||||||
|
# '-pedantic' sorgt dafuer, dass gcc streng arbeitet
|
||||||
|
CFLAGS = -c -pedantic -Wall
|
||||||
|
LFLAGS = -pedantic
|
||||||
|
OBJS = Counter.o CounterCtrl.o CounterState.o counterTest.o
|
||||||
|
|
||||||
|
counterTest: $(OBJS)
|
||||||
|
$(LINK) $(LFLAGS) -o counterTest $(OBJS)
|
||||||
|
|
||||||
|
counterTest.o: counterTest.cpp CounterCtrl.h
|
||||||
|
$(CC) $(CFLAGS) counterTest.cpp
|
||||||
|
|
||||||
|
Counter.o: Counter.cpp Counter.h
|
||||||
|
$(CC) $(CFLAGS) Counter.cpp
|
||||||
|
|
||||||
|
CounterCtrl.o: CounterCtrl.cpp CounterCtrl.h CounterState.h
|
||||||
|
$(CC) $(CFLAGS) CounterCtrl.cpp
|
||||||
|
|
||||||
|
CounterState.o: CounterState.cpp CounterState.h Counter.h CounterCtrl.h
|
||||||
|
$(CC) $(CFLAGS) CounterState.cpp
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f counterTest $(OBJS)
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"xmemory": "cpp",
|
||||||
|
"xstring": "cpp"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Counter.cpp
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Counter.h"
|
||||||
|
|
||||||
|
Counter::Counter(int val): countValue(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::count(int step)
|
||||||
|
{
|
||||||
|
countValue += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Counter::getCounter() const
|
||||||
|
{
|
||||||
|
return countValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::setCounter(int val)
|
||||||
|
{
|
||||||
|
countValue = val;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Counter.h
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTER_H__
|
||||||
|
#define COUNTER_H__
|
||||||
|
|
||||||
|
class Counter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Counter(int val=0);
|
||||||
|
|
||||||
|
void count(int step);
|
||||||
|
// counts the counter up (step>0) or down (step<0) by step
|
||||||
|
|
||||||
|
int getCounter() const;
|
||||||
|
// returns the counter value
|
||||||
|
|
||||||
|
void setCounter(int val);
|
||||||
|
// sets the counter to val
|
||||||
|
private:
|
||||||
|
int countValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// CounterCtrl.cpp
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
// CounterCtrl is the Context class in the State pattern
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2018
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Counter.h"
|
||||||
|
#include "CounterState.h"
|
||||||
|
#include "CounterCtrl.h"
|
||||||
|
|
||||||
|
CounterCtrl::CounterCtrl(int initValue) :
|
||||||
|
entity(initValue),
|
||||||
|
pState(CounterState::init(entity)) // initial state
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::process(Event e)
|
||||||
|
{ // delegates all requests to CounterState
|
||||||
|
pState = pState->handle(entity, e); // entity: reference to entity class object
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// CounterCtrl.h
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTERCTRL_H__
|
||||||
|
#define COUNTERCTRL_H__
|
||||||
|
#include "Counter.h"
|
||||||
|
|
||||||
|
class CounterState; // forward declaration
|
||||||
|
|
||||||
|
class CounterCtrl
|
||||||
|
// this is the 'Context' class of the State pattern
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Event{evUp, // count upwards
|
||||||
|
evDown, // count downwards
|
||||||
|
evCount, // count (up or down)
|
||||||
|
evStop}; // stop counting
|
||||||
|
CounterCtrl(int initValue = 0);
|
||||||
|
void process(Event e);
|
||||||
|
// changes the state of the FSM based on the event 'e'
|
||||||
|
private:
|
||||||
|
Counter entity; // entity class
|
||||||
|
CounterState* pState; // holds the current state
|
||||||
|
};
|
||||||
|
#endif
|
@ -0,0 +1,150 @@
|
|||||||
|
//
|
||||||
|
// CounterState.cpp
|
||||||
|
//
|
||||||
|
// implements all states of an up/down-Counter
|
||||||
|
// this file contains all classes of the state machine.
|
||||||
|
// it may make sense to have separate files for each state
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2018
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "CounterState.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
//class CounterState
|
||||||
|
CounterState* CounterState::init(Counter& entity) // is static
|
||||||
|
{
|
||||||
|
CounterState* initState = IdleState::getInstance();
|
||||||
|
initState->entryAction(entity); // executes entry action into init state
|
||||||
|
return initState;
|
||||||
|
}
|
||||||
|
|
||||||
|
CounterState* CounterState::changeState(Counter& entity,
|
||||||
|
Action ptransAction,
|
||||||
|
CounterState* pnewState)
|
||||||
|
{
|
||||||
|
exitAction(entity); // polymorphic call of exit action
|
||||||
|
(this->*ptransAction)(entity); // call of transition action
|
||||||
|
pnewState->entryAction(entity); // polymorphic call of entry action
|
||||||
|
return pnewState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterState::showCounter(Counter& entity)
|
||||||
|
{
|
||||||
|
cout << "counter = " << entity.getCounter() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterState::countUp(Counter& entity)
|
||||||
|
{
|
||||||
|
entity.count(1);
|
||||||
|
cout << "counter = " << entity.getCounter() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterState::countDown(Counter& entity)
|
||||||
|
{
|
||||||
|
entity.count(-1);
|
||||||
|
cout << "counter = " << entity.getCounter() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// class IdleState
|
||||||
|
IdleState IdleState::instance;
|
||||||
|
IdleState* IdleState::getInstance()
|
||||||
|
{
|
||||||
|
return &instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
CounterState* IdleState::handle(Counter& entity, CounterCtrl::Event e)
|
||||||
|
{
|
||||||
|
cout << "State: idleState" << endl;
|
||||||
|
if (CounterCtrl::evUp == e)
|
||||||
|
{
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, &IdleState::showCounter, CountUpState::getInstance());
|
||||||
|
}
|
||||||
|
else if (CounterCtrl::evDown == e)
|
||||||
|
{
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, &IdleState::showCounter, CountDownState::getInstance());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdleState::entryAction(Counter& entity)
|
||||||
|
{
|
||||||
|
cout << "Entering idleState" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdleState::exitAction(Counter& entity)
|
||||||
|
{
|
||||||
|
cout << "Exiting from idleState" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// class CountUpState
|
||||||
|
CountUpState CountUpState::instance;
|
||||||
|
CountUpState* CountUpState::getInstance()
|
||||||
|
{
|
||||||
|
return &instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
CounterState* CountUpState::handle(Counter& entity, CounterCtrl::Event e)
|
||||||
|
{
|
||||||
|
cout << "State: countUpState" << endl;
|
||||||
|
if (CounterCtrl::evCount == e)
|
||||||
|
{
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, &CountUpState::countUp, CountUpState::getInstance());
|
||||||
|
}
|
||||||
|
else if (CounterCtrl::evStop == e)
|
||||||
|
{
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, &CountUpState::emptyAction, IdleState::getInstance());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CountUpState::entryAction(Counter& entity)
|
||||||
|
{
|
||||||
|
cout << "Entering countUpState" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CountUpState::exitAction(Counter& entity)
|
||||||
|
{
|
||||||
|
cout << "Exiting from countUpState" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// class CountDownState
|
||||||
|
CountDownState CountDownState::instance;
|
||||||
|
CountDownState* CountDownState::getInstance()
|
||||||
|
{
|
||||||
|
return &instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
CounterState* CountDownState::handle(Counter& entity, CounterCtrl::Event e)
|
||||||
|
{
|
||||||
|
cout << "State: countDownState" << endl;
|
||||||
|
if (CounterCtrl::evCount == e)
|
||||||
|
{
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, &CountDownState::countDown, CountDownState::getInstance());
|
||||||
|
}
|
||||||
|
else if (CounterCtrl::evStop == e)
|
||||||
|
{
|
||||||
|
// state transition
|
||||||
|
return changeState(entity, &CountDownState::emptyAction, IdleState::getInstance());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CountDownState::entryAction(Counter& entity)
|
||||||
|
{
|
||||||
|
cout << "Entering countDownState" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CountDownState::exitAction(Counter& entity)
|
||||||
|
{
|
||||||
|
cout << "Exiting from countDownState" << endl;
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
//
|
||||||
|
// CounterState.h
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
// this file contains all classes of the state machine
|
||||||
|
// it may make sense to have separate files for each state
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Oct. 2018
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTERSTATE_H__
|
||||||
|
#define COUNTERSTATE_H__
|
||||||
|
#include "CounterCtrl.h"
|
||||||
|
|
||||||
|
class CounterState // abstract base class
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static CounterState* init(Counter& entity);
|
||||||
|
// should be called first, returns new state
|
||||||
|
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e) = 0;
|
||||||
|
// returns new state
|
||||||
|
protected:
|
||||||
|
virtual void entryAction(Counter& entity) {};
|
||||||
|
virtual void exitAction(Counter& entity) {};
|
||||||
|
typedef void (CounterState::*Action)(Counter& entity); // ptr to action function
|
||||||
|
CounterState* changeState(Counter& entity, Action ptransAction, CounterState* pnewState);
|
||||||
|
|
||||||
|
// transition actions
|
||||||
|
void emptyAction(Counter& entity) {};
|
||||||
|
void showCounter(Counter& entity);
|
||||||
|
void countUp(Counter& entity);
|
||||||
|
void countDown(Counter& entity);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IdleState : public CounterState // it's a singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static IdleState* getInstance();
|
||||||
|
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
|
||||||
|
protected:
|
||||||
|
virtual void entryAction(Counter& entity);
|
||||||
|
virtual void exitAction(Counter& entity);
|
||||||
|
private:
|
||||||
|
IdleState() {};
|
||||||
|
static IdleState instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CountUpState : public CounterState // it's a singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static CountUpState* getInstance();
|
||||||
|
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
|
||||||
|
protected:
|
||||||
|
virtual void entryAction(Counter& entity);
|
||||||
|
virtual void exitAction(Counter& entity);
|
||||||
|
private:
|
||||||
|
CountUpState() {};
|
||||||
|
static CountUpState instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CountDownState : public CounterState // it's a singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static CountDownState* getInstance();
|
||||||
|
virtual CounterState* handle(Counter& entity, CounterCtrl::Event e);
|
||||||
|
protected:
|
||||||
|
virtual void entryAction(Counter& entity);
|
||||||
|
virtual void exitAction(Counter& entity);
|
||||||
|
private:
|
||||||
|
CountDownState() {};
|
||||||
|
static CountDownState instance;
|
||||||
|
};
|
||||||
|
#endif
|
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// counterTest.cpp
|
||||||
|
//
|
||||||
|
// Test program for the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Nov. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "CounterCtrl.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char answer;
|
||||||
|
CounterCtrl myFsm;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cout << endl << "-------------------------------------------" << endl;
|
||||||
|
cout << " u Count up" << endl;
|
||||||
|
cout << " d Count down" << endl;
|
||||||
|
cout << " c Count" << endl;
|
||||||
|
cout << " s Stop counting" << endl;
|
||||||
|
cout << " q Quit" << endl;
|
||||||
|
|
||||||
|
cout << endl << "Please press key: ";
|
||||||
|
cin >> answer;
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
switch (answer)
|
||||||
|
{
|
||||||
|
case 'u':
|
||||||
|
myFsm.process(CounterCtrl::evUp);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
myFsm.process(CounterCtrl::evDown);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
myFsm.process(CounterCtrl::evCount);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
myFsm.process(CounterCtrl::evStop);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (answer != 'q');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
|||||||
|
#
|
||||||
|
# Makefile fuer Counter-Programm
|
||||||
|
# File: makefile
|
||||||
|
# Reto Bonderer, 21.10.2017
|
||||||
|
#
|
||||||
|
CC = g++
|
||||||
|
LINK = g++
|
||||||
|
# '-pedantic' sorgt dafuer, dass g++ streng arbeitet
|
||||||
|
CFLAGS = -c -pedantic -Wall
|
||||||
|
LFLAGS = -pedantic
|
||||||
|
OBJS = Counter.o CounterCtrl.o CounterState.o counterTest.o
|
||||||
|
EXE = counterTest
|
||||||
|
|
||||||
|
$(EXE): $(OBJS)
|
||||||
|
$(LINK) $(LFLAGS) -o $(EXE) $(OBJS)
|
||||||
|
|
||||||
|
counterTest.o: counterTest.cpp CounterCtrl.h
|
||||||
|
$(CC) $(CFLAGS) counterTest.cpp
|
||||||
|
|
||||||
|
Counter.o: Counter.cpp Counter.h
|
||||||
|
$(CC) $(CFLAGS) Counter.cpp
|
||||||
|
|
||||||
|
CounterCtrl.o: CounterCtrl.cpp CounterCtrl.h CounterState.h
|
||||||
|
$(CC) $(CFLAGS) CounterCtrl.cpp
|
||||||
|
|
||||||
|
CounterState.o: CounterState.cpp CounterState.h Counter.h
|
||||||
|
$(CC) $(CFLAGS) CounterState.cpp
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(EXE) $(OBJS)
|
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Counter.cpp
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Counter.h"
|
||||||
|
|
||||||
|
Counter::Counter(int val): countValue(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::count(int step)
|
||||||
|
{
|
||||||
|
countValue += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Counter::getCounter() const
|
||||||
|
{
|
||||||
|
return countValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::setCounter(int val)
|
||||||
|
{
|
||||||
|
countValue = val;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Counter.h
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTER_H__
|
||||||
|
#define COUNTER_H__
|
||||||
|
|
||||||
|
class Counter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Counter(int val);
|
||||||
|
|
||||||
|
void count(int step);
|
||||||
|
// counts the counter up (step>0) or down (step<0) by step
|
||||||
|
|
||||||
|
int getCounter() const;
|
||||||
|
// returns the counter value
|
||||||
|
|
||||||
|
void setCounter(int val);
|
||||||
|
// sets the counter to val
|
||||||
|
private:
|
||||||
|
int countValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,104 @@
|
|||||||
|
//
|
||||||
|
// CounterCtrl.cpp
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter as a table
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "CounterCtrl.h"
|
||||||
|
#include "Counter.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
const CounterCtrl::Transition CounterCtrl::fsm[] = // this table defines the fsm
|
||||||
|
{//currentState checker function action function next state
|
||||||
|
{idleState, &CounterCtrl::checkIdleUp, &CounterCtrl::actionIdleUp, countUpState},
|
||||||
|
{idleState, &CounterCtrl::checkIdleDown, &CounterCtrl::actionIdleDown, countDownState},
|
||||||
|
{countUpState, &CounterCtrl::checkUpUp, &CounterCtrl::actionUpUp, countUpState},
|
||||||
|
{countUpState, &CounterCtrl::checkUpIdle, &CounterCtrl::actionUpIdle, idleState},
|
||||||
|
{countDownState, &CounterCtrl::checkDownDown, &CounterCtrl::actionDownDown, countDownState},
|
||||||
|
{countDownState, &CounterCtrl::checkDownIdle, &CounterCtrl::actionDownIdle, idleState}
|
||||||
|
};
|
||||||
|
|
||||||
|
CounterCtrl::CounterCtrl(int initValue) :
|
||||||
|
currentState(idleState),
|
||||||
|
myCounter(initValue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::process(Event e) // this function never changes
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < sizeof(fsm) / sizeof(Transition); ++i) // let compiler determine number of transitions
|
||||||
|
{
|
||||||
|
if (fsm[i].currentState == currentState && // is there an entry in the table?
|
||||||
|
(this->*fsm[i].pChecker)(e))
|
||||||
|
{
|
||||||
|
(this->*fsm[i].pAction)();
|
||||||
|
currentState = fsm[i].nextState;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check functions
|
||||||
|
bool CounterCtrl::checkIdleUp(Event e)
|
||||||
|
{
|
||||||
|
return evUp == e;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CounterCtrl::checkIdleDown(Event e)
|
||||||
|
{
|
||||||
|
return evDown == e;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CounterCtrl::checkUpIdle(Event e)
|
||||||
|
{
|
||||||
|
return evStop == e;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CounterCtrl::checkDownIdle(Event e)
|
||||||
|
{
|
||||||
|
return evStop == e;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CounterCtrl::checkUpUp(Event e)
|
||||||
|
{
|
||||||
|
return evCount == e;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CounterCtrl::checkDownDown(Event e)
|
||||||
|
{
|
||||||
|
return evCount == e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// action functions
|
||||||
|
void CounterCtrl::actionIdleUp(void)
|
||||||
|
{
|
||||||
|
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::actionIdleDown(void)
|
||||||
|
{
|
||||||
|
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::actionUpIdle(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::actionDownIdle(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::actionUpUp(void)
|
||||||
|
{
|
||||||
|
myCounter.count(1);
|
||||||
|
cout << "State: countUpState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::actionDownDown(void)
|
||||||
|
{
|
||||||
|
myCounter.count(-1);
|
||||||
|
cout << "State: countDownState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// CounterCtrl.h
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter as a table
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTERCTRL_H__
|
||||||
|
#define COUNTERCTRL_H__
|
||||||
|
#include "Counter.h"
|
||||||
|
|
||||||
|
class CounterCtrl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Event{evUp, // count upwards
|
||||||
|
evDown, // count downwards
|
||||||
|
evCount, // count (up or down)
|
||||||
|
evStop}; // stop counting
|
||||||
|
CounterCtrl(int initValue = 0);
|
||||||
|
void process(Event e);
|
||||||
|
// changes the state of the FSM based on the event 'e'
|
||||||
|
// starts the actions
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum State{idleState, // idle state
|
||||||
|
countUpState, // counting up at each count event
|
||||||
|
countDownState}; // counting down at each count event
|
||||||
|
|
||||||
|
State currentState; // holds the current state of the FSM
|
||||||
|
Counter myCounter;
|
||||||
|
|
||||||
|
typedef bool (CounterCtrl::*Checker)(Event); // function ptr for checker function
|
||||||
|
typedef void (CounterCtrl::*Action)(void); // function ptr for action function
|
||||||
|
// check functions
|
||||||
|
bool checkIdleUp(Event e);
|
||||||
|
bool checkIdleDown(Event e);
|
||||||
|
bool checkUpIdle(Event e);
|
||||||
|
bool checkDownIdle(Event e);
|
||||||
|
bool checkUpUp(Event e);
|
||||||
|
bool checkDownDown(Event e);
|
||||||
|
|
||||||
|
// action functions
|
||||||
|
void actionIdleUp(void);
|
||||||
|
void actionIdleDown(void);
|
||||||
|
void actionUpIdle(void);
|
||||||
|
void actionDownIdle(void);
|
||||||
|
void actionUpUp(void);
|
||||||
|
void actionDownDown(void);
|
||||||
|
|
||||||
|
struct Transition
|
||||||
|
{
|
||||||
|
State currentState; // current state
|
||||||
|
Checker pChecker; // pointer to checker function
|
||||||
|
Action pAction; // pointer to action function
|
||||||
|
State nextState; // next state
|
||||||
|
};
|
||||||
|
static const Transition fsm[];
|
||||||
|
};
|
||||||
|
#endif
|
Binary file not shown.
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// counterTest.cpp
|
||||||
|
//
|
||||||
|
// Test program for the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "CounterCtrl.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char answer;
|
||||||
|
CounterCtrl myFsm(0);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cout << endl << "-------------------------------------------" << endl;
|
||||||
|
cout << " u Count up" << endl;
|
||||||
|
cout << " d Count down" << endl;
|
||||||
|
cout << " c Count" << endl;
|
||||||
|
cout << " s Stop counting" << endl;
|
||||||
|
cout << " q Quit" << endl;
|
||||||
|
|
||||||
|
cout << endl << "Please press key: ";
|
||||||
|
cin >> answer;
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
switch (answer)
|
||||||
|
{
|
||||||
|
case 'u':
|
||||||
|
myFsm.process(CounterCtrl::evUp);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
myFsm.process(CounterCtrl::evDown);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
myFsm.process(CounterCtrl::evCount);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
myFsm.process(CounterCtrl::evStop);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (answer != 'q');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
@ -0,0 +1,26 @@
|
|||||||
|
#
|
||||||
|
# Makefile fuer Counter-Programm
|
||||||
|
# File: makefile
|
||||||
|
# Reto Bonderer, 07.10.2017
|
||||||
|
#
|
||||||
|
CC = g++
|
||||||
|
LINK = g++
|
||||||
|
CFLAGS = -c -Wall
|
||||||
|
LFLAGS = -Wall
|
||||||
|
OBJS = Counter.o CounterCtrl.o counterTest.o
|
||||||
|
EXE = counterTest
|
||||||
|
|
||||||
|
$(EXE): $(OBJS)
|
||||||
|
$(LINK) $(LFLAGS) -o $(EXE) $(OBJS)
|
||||||
|
|
||||||
|
counterTest.o: counterTest.cpp CounterCtrl.h
|
||||||
|
$(CC) $(CFLAGS) counterTest.cpp
|
||||||
|
|
||||||
|
Counter.o: Counter.cpp Counter.h
|
||||||
|
$(CC) $(CFLAGS) Counter.cpp
|
||||||
|
|
||||||
|
CounterCtrl.o: CounterCtrl.cpp CounterCtrl.h Counter.h
|
||||||
|
$(CC) $(CFLAGS) CounterCtrl.cpp
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(EXE) $(OBJS)
|
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Counter.cpp
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Counter.h"
|
||||||
|
|
||||||
|
Counter::Counter(int val): countValue(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::count(int step)
|
||||||
|
{
|
||||||
|
countValue += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Counter::getCounter() const
|
||||||
|
{
|
||||||
|
return countValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::setCounter(int val)
|
||||||
|
{
|
||||||
|
countValue = val;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Counter.h
|
||||||
|
//
|
||||||
|
// implements an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTER_H__
|
||||||
|
#define COUNTER_H__
|
||||||
|
|
||||||
|
class Counter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Counter(int val);
|
||||||
|
|
||||||
|
void count(int step);
|
||||||
|
// counts the counter up (step>0) or down (step<0) by step
|
||||||
|
|
||||||
|
int getCounter() const;
|
||||||
|
// returns the counter value
|
||||||
|
|
||||||
|
void setCounter(int val);
|
||||||
|
// sets the counter to val
|
||||||
|
private:
|
||||||
|
int countValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// CounterCtrl.cpp
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter as a simple table
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "CounterCtrl.h"
|
||||||
|
#include "Counter.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
const CounterCtrl::Transition CounterCtrl::fsm[] = // this table defines the fsm
|
||||||
|
{//currentState triggering event action function next state
|
||||||
|
{idleState, evUp, &CounterCtrl::actionIdleUp, countUpState},
|
||||||
|
{idleState, evDown, &CounterCtrl::actionIdleDown, countDownState},
|
||||||
|
{countUpState, evCount, &CounterCtrl::actionUpUp, countUpState},
|
||||||
|
{countUpState, evStop, &CounterCtrl::actionDoNothing, idleState},
|
||||||
|
{countDownState, evCount, &CounterCtrl::actionDownDown, countDownState},
|
||||||
|
{countDownState, evStop, &CounterCtrl::actionDoNothing, idleState}
|
||||||
|
};
|
||||||
|
|
||||||
|
CounterCtrl::CounterCtrl(int initValue) :
|
||||||
|
currentState(idleState),
|
||||||
|
myCounter(initValue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::process(Event e) // execution engine, this function never changes
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < sizeof(fsm) / sizeof(Transition); ++i) // determine number of transitions automatically
|
||||||
|
{
|
||||||
|
if (fsm[i].currentState == currentState && fsm[i].ev == e) // is there an entry in the table?
|
||||||
|
{
|
||||||
|
(this->*fsm[i].pAction)();
|
||||||
|
currentState = fsm[i].nextState;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// action functions
|
||||||
|
void CounterCtrl::actionIdleUp(void)
|
||||||
|
{
|
||||||
|
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::actionIdleDown(void)
|
||||||
|
{
|
||||||
|
cout << "State: idleState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::actionDoNothing(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::actionUpUp(void)
|
||||||
|
{
|
||||||
|
myCounter.count(1);
|
||||||
|
cout << "State: countUpState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CounterCtrl::actionDownDown(void)
|
||||||
|
{
|
||||||
|
myCounter.count(-1);
|
||||||
|
cout << "State: countDownState, counter = " << myCounter.getCounter() << endl;
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// CounterCtrl.h
|
||||||
|
//
|
||||||
|
// implements the Finite State Machine (FSM) of an up/down-Counter as a simple table
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COUNTERCTRL_H__
|
||||||
|
#define COUNTERCTRL_H__
|
||||||
|
#include "Counter.h"
|
||||||
|
|
||||||
|
class CounterCtrl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Event{evUp, // count upwards
|
||||||
|
evDown, // count downwards
|
||||||
|
evCount, // count (up or down)
|
||||||
|
evStop}; // stop counting
|
||||||
|
CounterCtrl(int initValue = 0);
|
||||||
|
void process(Event e);
|
||||||
|
// changes the state of the FSM based on the event 'e'
|
||||||
|
// starts the actions
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum State{idleState, // idle state
|
||||||
|
countUpState, // counting up at each count event
|
||||||
|
countDownState}; // counting down at each count event
|
||||||
|
|
||||||
|
State currentState; // holds the current state of the FSM
|
||||||
|
Counter myCounter;
|
||||||
|
|
||||||
|
typedef void (CounterCtrl::*Action)(void); // function ptr for action function
|
||||||
|
|
||||||
|
// action functions
|
||||||
|
void actionIdleUp(void);
|
||||||
|
void actionIdleDown(void);
|
||||||
|
void actionDoNothing(void);
|
||||||
|
void actionUpUp(void);
|
||||||
|
void actionDownDown(void);
|
||||||
|
|
||||||
|
struct Transition
|
||||||
|
{
|
||||||
|
State currentState; // current state
|
||||||
|
Event ev; // event triggering the transition
|
||||||
|
Action pAction; // pointer to action function
|
||||||
|
State nextState; // next state
|
||||||
|
};
|
||||||
|
static const Transition fsm[];
|
||||||
|
};
|
||||||
|
#endif
|
Binary file not shown.
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// counterTest.cpp
|
||||||
|
//
|
||||||
|
// Test program for the Finite State Machine (FSM) of an up/down-Counter
|
||||||
|
//
|
||||||
|
// (C) R. Bonderer, HSR Hochschule Rapperswil, Okt. 2017
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "CounterCtrl.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char answer;
|
||||||
|
CounterCtrl myFsm;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cout << endl << "-------------------------------------------" << endl;
|
||||||
|
cout << " u Count up" << endl;
|
||||||
|
cout << " d Count down" << endl;
|
||||||
|
cout << " c Count" << endl;
|
||||||
|
cout << " s Stop counting" << endl;
|
||||||
|
cout << " q Quit" << endl;
|
||||||
|
|
||||||
|
cout << endl << "Please press key: ";
|
||||||
|
cin >> answer;
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
switch (answer)
|
||||||
|
{
|
||||||
|
case 'u':
|
||||||
|
myFsm.process(CounterCtrl::evUp);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
myFsm.process(CounterCtrl::evDown);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
myFsm.process(CounterCtrl::evCount);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
myFsm.process(CounterCtrl::evStop);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (answer != 'q');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
#
|
||||||
|
# Makefile fuer Counter-Programm
|
||||||
|
# File: makefile
|
||||||
|
# Reto Bonderer, 07.10.2017
|
||||||
|
#
|
||||||
|
CC = g++
|
||||||
|
LINK = g++
|
||||||
|
CFLAGS = -c -Wall
|
||||||
|
LFLAGS = -Wall
|
||||||
|
OBJS = Counter.o CounterCtrl.o counterTest.o
|
||||||
|
EXE = counterTest
|
||||||
|
|
||||||
|
$(EXE): $(OBJS)
|
||||||
|
$(LINK) $(LFLAGS) -o $(EXE) $(OBJS)
|
||||||
|
|
||||||
|
counterTest.o: counterTest.cpp CounterCtrl.h
|
||||||
|
$(CC) $(CFLAGS) counterTest.cpp
|
||||||
|
|
||||||
|
Counter.o: Counter.cpp Counter.h
|
||||||
|
$(CC) $(CFLAGS) Counter.cpp
|
||||||
|
|
||||||
|
CounterCtrl.o: CounterCtrl.cpp CounterCtrl.h Counter.h
|
||||||
|
$(CC) $(CFLAGS) CounterCtrl.cpp
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(EXE) $(OBJS)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,194 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* STDINT.H v5.2.1 */
|
||||||
|
/* Copyright (c) 2002-2009 Texas Instruments Incorporated */
|
||||||
|
/*****************************************************************************/
|
||||||
|
#ifndef _STDINT_H_
|
||||||
|
#define _STDINT_H_
|
||||||
|
|
||||||
|
/* 7.18.1.1 Exact-width integer types */
|
||||||
|
|
||||||
|
typedef int int16_t;
|
||||||
|
typedef unsigned int uint16_t;
|
||||||
|
typedef long int32_t;
|
||||||
|
typedef unsigned long uint32_t;
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
|
||||||
|
typedef long long int64_t;
|
||||||
|
typedef unsigned long long uint64_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 7.18.1.2 Minimum-width integer types */
|
||||||
|
|
||||||
|
typedef int16_t int_least8_t;
|
||||||
|
typedef uint16_t uint_least8_t;
|
||||||
|
|
||||||
|
typedef int16_t int_least16_t;
|
||||||
|
typedef uint16_t uint_least16_t;
|
||||||
|
typedef int32_t int_least32_t;
|
||||||
|
typedef uint32_t uint_least32_t;
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
|
||||||
|
typedef int64_t int_least64_t;
|
||||||
|
typedef uint64_t uint_least64_t;
|
||||||
|
#else
|
||||||
|
/* sorry, int_least64_t not implemented for C54x, C55x, MSP430 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 7.18.1.3 Fastest minimum-width integer types */
|
||||||
|
|
||||||
|
typedef int16_t int_fast8_t;
|
||||||
|
typedef uint16_t uint_fast8_t;
|
||||||
|
typedef int16_t int_fast16_t;
|
||||||
|
typedef uint16_t uint_fast16_t;
|
||||||
|
|
||||||
|
typedef int32_t int_fast32_t;
|
||||||
|
typedef uint32_t uint_fast32_t;
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
|
||||||
|
typedef int64_t int_fast64_t;
|
||||||
|
typedef uint64_t uint_fast64_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 7.18.1.4 Integer types capable of holding object pointers */
|
||||||
|
typedef long intptr_t;
|
||||||
|
typedef unsigned long uintptr_t;
|
||||||
|
|
||||||
|
/* 7.18.1.5 Greatest-width integer types */
|
||||||
|
#if defined(__TMS320C55X__) || defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
|
||||||
|
typedef long long intmax_t;
|
||||||
|
typedef unsigned long long uintmax_t;
|
||||||
|
#elif defined(_TMS320C5XX) || defined(__TMS320C27X__) || defined(__MSP430__)
|
||||||
|
typedef long intmax_t;
|
||||||
|
typedef unsigned long uintmax_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
According to footnotes in the 1999 C standard, "C++ implementations
|
||||||
|
should define these macros only when __STDC_LIMIT_MACROS is defined
|
||||||
|
before <stdint.h> is included."
|
||||||
|
*/
|
||||||
|
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
|
||||||
|
|
||||||
|
/* 7.18.2 Limits of specified width integer types */
|
||||||
|
|
||||||
|
|
||||||
|
#define INT16_MAX 0x7fff
|
||||||
|
#define INT16_MIN (-INT16_MAX-1)
|
||||||
|
#define UINT16_MAX 0xffff
|
||||||
|
|
||||||
|
#define INT32_MAX 0x7fffffff
|
||||||
|
#define INT32_MIN (-INT32_MAX-1)
|
||||||
|
#define UINT32_MAX 0xffffffff
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
|
||||||
|
#define INT64_MAX 0x7fffffffffffffff
|
||||||
|
#define INT64_MIN (-INT64_MAX-1)
|
||||||
|
#define UINT64_MAX 0xffffffffffffffff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define INT_LEAST8_MAX INT16_MAX
|
||||||
|
#define INT_LEAST8_MIN INT16_MIN
|
||||||
|
#define UINT_LEAST8_MAX UINT16_MAX
|
||||||
|
|
||||||
|
#define INT_LEAST16_MAX INT16_MAX
|
||||||
|
#define INT_LEAST16_MIN INT16_MIN
|
||||||
|
#define UINT_LEAST16_MAX UINT16_MAX
|
||||||
|
#define INT_LEAST32_MAX INT32_MAX
|
||||||
|
#define INT_LEAST32_MIN INT32_MIN
|
||||||
|
#define UINT_LEAST32_MAX UINT32_MAX
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
|
||||||
|
#define INT_LEAST64_MAX INT64_MAX
|
||||||
|
#define INT_LEAST64_MIN INT64_MIN
|
||||||
|
#define UINT_LEAST64_MAX UINT64_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define INT_FAST8_MAX INT16_MAX
|
||||||
|
#define INT_FAST8_MIN INT16_MIN
|
||||||
|
#define UINT_FAST8_MAX UINT16_MAX
|
||||||
|
#define INT_FAST16_MAX INT16_MAX
|
||||||
|
#define INT_FAST16_MIN INT16_MIN
|
||||||
|
#define UINT_FAST16_MAX UINT16_MAX
|
||||||
|
|
||||||
|
#define INT_FAST32_MAX INT32_MAX
|
||||||
|
#define INT_FAST32_MIN INT32_MIN
|
||||||
|
#define UINT_FAST32_MAX UINT32_MAX
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
|
||||||
|
#define INT_FAST64_MAX INT64_MAX
|
||||||
|
#define INT_FAST64_MIN INT64_MIN
|
||||||
|
#define UINT_FAST64_MAX UINT64_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define INTPTR_MAX INT32_MAX
|
||||||
|
#define INTPTR_MIN INT32_MIN
|
||||||
|
#define UINTPTR_MAX UINT32_MAX
|
||||||
|
|
||||||
|
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
|
||||||
|
#define INTMAX_MIN INT64_MIN
|
||||||
|
#define INTMAX_MAX INT64_MAX
|
||||||
|
#define UINTMAX_MAX UINT64_MAX
|
||||||
|
#elif defined(_TMS320C5XX) || defined(__TMS320C27X__) || defined(__MSP430__)
|
||||||
|
#define INTMAX_MIN INT32_MIN
|
||||||
|
#define INTMAX_MAX INT32_MAX
|
||||||
|
#define UINTMAX_MAX UINT32_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 7.18.3 Limits of other integer types */
|
||||||
|
|
||||||
|
#define PTRDIFF_MAX INT32_MAX
|
||||||
|
#define PTRDIFF_MIN INT32_MIN
|
||||||
|
|
||||||
|
#define SIG_ATOMIC_MIN INT32_MIN
|
||||||
|
#define SIG_ATOMIC_MAX INT32_MAX
|
||||||
|
|
||||||
|
#define SIZE_MAX INT32_MAX
|
||||||
|
|
||||||
|
#ifndef WCHAR_MAX
|
||||||
|
#define WCHAR_MAX 0xffffu
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WCHAR_MIN
|
||||||
|
#define WCHAR_MIN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WINT_MIN INT32_MIN
|
||||||
|
#define WINT_MAX INT32_MAX
|
||||||
|
|
||||||
|
/* 7.18.4.1 Macros for minimum-width integer constants */
|
||||||
|
|
||||||
|
/*
|
||||||
|
There is a defect report filed against the C99 standard concerning how
|
||||||
|
the (U)INTN_C macros should be implemented. Please refer to --
|
||||||
|
http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_209.htm
|
||||||
|
for more information. These macros are implemented according to the
|
||||||
|
suggestion given at this web site.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define INT8_C(value) ((int_least8_t)(value))
|
||||||
|
#define UINT8_C(value) ((uint_least8_t)(value))
|
||||||
|
#define INT16_C(value) ((int_least16_t)(value))
|
||||||
|
#define UINT16_C(value) ((uint_least16_t)(value))
|
||||||
|
#define INT32_C(value) ((int_least32_t)(value))
|
||||||
|
#define UINT32_C(value) ((uint_least32_t)(value))
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__TMS470__) || defined(_TMS320C6X) || defined(__TMS320C28X__)
|
||||||
|
#define INT64_C(value) ((int_least64_t)(value))
|
||||||
|
#define UINT64_C(value) ((uint_least64_t)(value))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 7.18.4.2 Macros for greatest-width integer constants */
|
||||||
|
|
||||||
|
#define INTMAX_C(value) ((intmax_t)(value))
|
||||||
|
#define UINTMAX_C(value) ((uintmax_t)(value))
|
||||||
|
|
||||||
|
#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */
|
||||||
|
|
||||||
|
#endif /* _STDINT_H_ */
|
@ -0,0 +1,29 @@
|
|||||||
|
cpp_src = $(wildcard *.cpp)
|
||||||
|
#cpp_src += $(wildcard ./utils/*.cpp)
|
||||||
|
#cpp_src += $(wildcard ./driver/*.cpp)
|
||||||
|
|
||||||
|
cpp_obj = $(cpp_src:.cpp=.o)
|
||||||
|
c_obj = $(c_src:.c=.o)
|
||||||
|
CC = g++
|
||||||
|
CFLAGS = -Wall -pedantic -li2c
|
||||||
|
LDFLAGS =
|
||||||
|
EXEC = runtest
|
||||||
|
|
||||||
|
|
||||||
|
all : $(EXEC)
|
||||||
|
|
||||||
|
$(EXEC): $(cpp_obj) $(c_obj)
|
||||||
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
debug : $(EXEC)
|
||||||
|
|
||||||
|
$(EXEC): $(cpp_obj) $(c_obj)
|
||||||
|
$(CC) -g -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
||||||
|
|
||||||
|
cleanall:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef __HW_PLATTFORM_HPP__
|
||||||
|
#define __HW_PLATTFORM_HPP__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
//
|
||||||
|
// csl ressources
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "./../csl/implementations/dummy/dummy_pin.hpp"
|
||||||
|
|
||||||
|
//
|
||||||
|
// drivers
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "./../drivers/LED.hpp"
|
||||||
|
|
||||||
|
struct HW_plattform
|
||||||
|
{
|
||||||
|
HW_plattform():
|
||||||
|
pin_0(),
|
||||||
|
pin_1(),
|
||||||
|
led_0(pin_0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
std::cout << "bsl init..." << std::endl;
|
||||||
|
pin_0.set(false);
|
||||||
|
pin_1.set(false);
|
||||||
|
std::cout << "...done!" << std::endl;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Dummy_Pin pin_0, pin_1;
|
||||||
|
public:
|
||||||
|
|
||||||
|
LED<Dummy_Pin> led_0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __HW_PLATTFORM_HPP__
|
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef __AVR_PIN_HPP__
|
||||||
|
#define __AVR_PIN_HPP__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "./../../interfaces/pin.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct AVR_Pin : Pin<AVR_Pin>
|
||||||
|
{
|
||||||
|
AVR_Pin()
|
||||||
|
{
|
||||||
|
std::cout << "created AVR_Pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setImp(bool logic)
|
||||||
|
{
|
||||||
|
std::cout << "AVR pin set to " << logic << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleImp()
|
||||||
|
{
|
||||||
|
std::cout << "toggled AVR pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getImp()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_stuff()
|
||||||
|
{
|
||||||
|
std::cout << "AVR specific stuff" << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __AVR_PIN_HPP__
|
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef __DUMMY_PIN_HPP__
|
||||||
|
#define __DUMMY_PIN_HPP__
|
||||||
|
|
||||||
|
#include "./../../interfaces/pin.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
struct Dummy_Pin : Pin<Dummy_Pin>
|
||||||
|
{
|
||||||
|
Dummy_Pin()
|
||||||
|
{
|
||||||
|
std::cout << "created Dummy_Pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setImp(bool logic)
|
||||||
|
{
|
||||||
|
std::cout << "Dummy pin set to " << logic << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleImp()
|
||||||
|
{
|
||||||
|
std::cout << "toggled Dummy pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getImp()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dummy_stuff()
|
||||||
|
{
|
||||||
|
std::cout << "dummy specific stuff" << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __DUMMY_PIN_HPP__
|
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef __STM_PIN_HPP__
|
||||||
|
#define __STM_PIN_HPP__
|
||||||
|
|
||||||
|
#include "./../../interfaces/pin.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
truct STM32_Pin : Pin<STM32_Pin>
|
||||||
|
{
|
||||||
|
STM32_Pin()
|
||||||
|
{
|
||||||
|
std::cout << "created STM32_Pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setImp(bool logic)
|
||||||
|
{
|
||||||
|
std::cout << "stm32 pin set to " << logic << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleImp()
|
||||||
|
{
|
||||||
|
std::cout << "toggled stm32 pin" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getImp()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void STM32_stuff()
|
||||||
|
{
|
||||||
|
std::cout << "STM_32 specific stuff" << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __STM_PIN_HPP__
|
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef __PIN_HPP__
|
||||||
|
#define __PIN_HPP__
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
|
struct Pin
|
||||||
|
{
|
||||||
|
void set(bool logic)
|
||||||
|
{
|
||||||
|
static_cast<Derived*>(this)->setImp(logic);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle()
|
||||||
|
{
|
||||||
|
static_cast<Derived*>(this)->toggleImp();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get(void)
|
||||||
|
{
|
||||||
|
return static_cast<Derived*>(this)->getImp();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __PIN_HPP__
|
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef __LED_HPP__
|
||||||
|
#define __LED_HPP__
|
||||||
|
|
||||||
|
#include "./../csl/interfaces/pin.hpp"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class LED
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
LED(Pin<T>& pin) :
|
||||||
|
pin(pin)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void turnOn()
|
||||||
|
{
|
||||||
|
pin.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void turnOff()
|
||||||
|
{
|
||||||
|
pin.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle()
|
||||||
|
{
|
||||||
|
pin.toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Pin<T>& pin;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __LED_HPP__
|
@ -0,0 +1,16 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "./bsl/hw_plattform.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
HW_plattform hw;
|
||||||
|
hw.init();
|
||||||
|
|
||||||
|
//hw.pin_1.set(true);
|
||||||
|
|
||||||
|
hw.led_0.turnOn();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
Binary file not shown.
@ -0,0 +1,24 @@
|
|||||||
|
cpp_src = $(wildcard *.cpp)
|
||||||
|
cpp_src += $(wildcard ./utils/*.cpp)
|
||||||
|
cpp_src += $(wildcard ./driver/*.cpp)
|
||||||
|
|
||||||
|
cpp_obj = $(cpp_src:.cpp=.o)
|
||||||
|
c_obj = $(c_src:.c=.o)
|
||||||
|
CC = g++
|
||||||
|
CFLAGS = -Wall -pedantic -li2c
|
||||||
|
LDFLAGS =
|
||||||
|
EXEC = runtest
|
||||||
|
|
||||||
|
|
||||||
|
all : $(EXEC)
|
||||||
|
|
||||||
|
$(EXEC): $(cpp_obj) $(c_obj)
|
||||||
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
||||||
|
|
||||||
|
cleanall:
|
||||||
|
rm -rf $(c_obj) $(cpp_obj) $(EXEC)
|
||||||
|
clear
|
@ -0,0 +1,69 @@
|
|||||||
|
#include "device.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
Device::Device() :
|
||||||
|
reg_control(0x00)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::cout << "Device::Device()" << std::endl;
|
||||||
|
std::cout << +reg_control.raw << std::endl;
|
||||||
|
|
||||||
|
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_OFF;
|
||||||
|
reg_control.bits.SPEED = Reg_Control::SPEED::STAND_STILL;
|
||||||
|
|
||||||
|
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
|
||||||
|
std::cout << "SPEED = " <<+reg_control.bits.SPEED << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::doSomething()
|
||||||
|
{
|
||||||
|
std::cout << "Device::doSomething()" << std::endl;
|
||||||
|
|
||||||
|
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
|
||||||
|
reg_control.bits.SPEED = Reg_Control::SPEED::FAST;
|
||||||
|
|
||||||
|
if(reg_control.bits.POWER_DEV == Reg_Control::POWER_DEV::TURN_ON){
|
||||||
|
std::cout << "device turned on!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
|
||||||
|
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
|
||||||
|
|
||||||
|
std::cout << +reg_control << std::endl;
|
||||||
|
|
||||||
|
reg_control = 0;
|
||||||
|
|
||||||
|
std::cout << +reg_control << std::endl;
|
||||||
|
|
||||||
|
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
|
||||||
|
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
|
||||||
|
|
||||||
|
//reg_control.bits.SPEED = Reg_Control::SPEED::FAST;
|
||||||
|
reg_control.bits.POWER_DEV = Reg_Control::POWER_DEV::TURN_ON;
|
||||||
|
|
||||||
|
std::cout << "POWER = " << +reg_control.bits.POWER_DEV << std::endl;
|
||||||
|
std::cout << "SPEED = " << +reg_control.bits.SPEED << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::status()
|
||||||
|
{
|
||||||
|
// imitating read hardware register (for example reading from device via SPI or i2c)
|
||||||
|
reg_motorStatus = 0xFE;
|
||||||
|
|
||||||
|
if(reg_motorStatus.bits.POWER == Reg_MotorStatus::POWER::ON) {
|
||||||
|
std::cout << "Motor is Powered ON!" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Motor is Powered OFF!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// will throw error because this bitfield is set const!
|
||||||
|
//reg_motorStatus.bits.STATUS = Reg_MotorStatus::STATUS::STANDSTILL;
|
||||||
|
|
||||||
|
std::cout << +reg_motorStatus.bits.POWER << std::endl;
|
||||||
|
|
||||||
|
std::cout << "Motor Status : " << +reg_motorStatus.bits.STATUS << std::endl;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue