parent
335be7f8c8
commit
c3104ab657
@ -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;
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
#ifndef _DEVICE_HPP_
|
||||||
|
#define _DEVICE_HPP_
|
||||||
|
|
||||||
|
#include "../utils/BitField.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class Device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Device();
|
||||||
|
|
||||||
|
void doSomething();
|
||||||
|
|
||||||
|
void status();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register declarations
|
||||||
|
//
|
||||||
|
#ifdef EXAMPLE_CODE_FOR_REFERENCE
|
||||||
|
union Control {
|
||||||
|
struct OPM{
|
||||||
|
typedef Bits<uint16_t, 10, 2> bits;
|
||||||
|
enum { NO_CHANGE = 0, AS_STANDBY = 1};
|
||||||
|
};
|
||||||
|
struct CTRL_BR{
|
||||||
|
enum { NO_CHANGE = 0, BRANCH_NORMAL = 1};
|
||||||
|
};
|
||||||
|
struct CTRL_BR1 : CTRL_BR{
|
||||||
|
typedef Bits<uint16_t, 8, 2> bits;
|
||||||
|
};
|
||||||
|
struct CTRL_BR2 : CTRL_BR{
|
||||||
|
typedef Bits<uint16_t, 6, 2> bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
union Bits {
|
||||||
|
Control::OPM::bits OPM;
|
||||||
|
Control::CTRL_BR1::bits CTRL_BR1;
|
||||||
|
Control::CTRL_BR2::bits CTRL_BR2;
|
||||||
|
} bits;
|
||||||
|
uint16_t raw;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
union Reg_Control
|
||||||
|
{
|
||||||
|
// bit 4
|
||||||
|
struct POWER_DEV{
|
||||||
|
typedef BitField<uint8_t, 7, 1> Bits;
|
||||||
|
enum{TURN_OFF = 0, TURN_ON = 1};
|
||||||
|
};
|
||||||
|
// bits 2-3
|
||||||
|
struct SPEED{
|
||||||
|
typedef BitField<uint8_t, 2, 2> Bits;
|
||||||
|
enum{STAND_STILL = 0,
|
||||||
|
SLOW = 1,
|
||||||
|
NORMAL = 2,
|
||||||
|
FAST = 3};
|
||||||
|
};
|
||||||
|
union Bits{
|
||||||
|
Reg_Control::POWER_DEV::Bits POWER_DEV;
|
||||||
|
Reg_Control::SPEED::Bits SPEED;
|
||||||
|
} bits;
|
||||||
|
// raw value. all bitfields will be "unified" here ;)
|
||||||
|
uint8_t raw;
|
||||||
|
// union Ctor with default value set to 0x00
|
||||||
|
Reg_Control(uint8_t v = 0x00) : raw(v) {}
|
||||||
|
// raw value extraction of register
|
||||||
|
operator uint8_t() {return raw;}
|
||||||
|
// used for updating software immage of hardware register
|
||||||
|
void operator = (uint8_t v) {raw = v;}
|
||||||
|
};
|
||||||
|
|
||||||
|
union Reg_MotorStatus
|
||||||
|
{
|
||||||
|
struct POWER{
|
||||||
|
typedef BitField<uint8_t,0,1> Bits;
|
||||||
|
enum{OFF = 0, ON = 1};
|
||||||
|
};
|
||||||
|
struct STATUS{
|
||||||
|
typedef BitField<uint8_t, 2,3>Bits;
|
||||||
|
enum{STANDSTILL = 0,
|
||||||
|
ACCELERATING_CW = 1,
|
||||||
|
DEACCELERATING_CW = 2,
|
||||||
|
ACCELERATING_CCW = 3,
|
||||||
|
DEACCELERATING_CCW = 4,
|
||||||
|
CONSTANT_SPEED = 5,
|
||||||
|
BLOCKED = 6};
|
||||||
|
};
|
||||||
|
union Bits
|
||||||
|
{
|
||||||
|
// is set const because it only used for status indication
|
||||||
|
const Reg_MotorStatus::POWER::Bits POWER;
|
||||||
|
const Reg_MotorStatus::STATUS::Bits STATUS;
|
||||||
|
}bits;
|
||||||
|
uint8_t raw;
|
||||||
|
|
||||||
|
Reg_MotorStatus(uint8_t v = 0x00) : raw(v) {}
|
||||||
|
operator uint8_t() {return raw;}
|
||||||
|
void operator = (uint8_t v) {raw = v;}
|
||||||
|
};
|
||||||
|
|
||||||
|
Reg_Control reg_control;
|
||||||
|
|
||||||
|
Reg_MotorStatus reg_motorStatus;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _DEVICE_HPP_
|
@ -0,0 +1,64 @@
|
|||||||
|
#ifdef __MAX31865_HPP_
|
||||||
|
#define __MAX31865_HPP__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../utils/BitFiled.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
class MAX31865
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MAX31865();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//
|
||||||
|
// register definitions
|
||||||
|
//
|
||||||
|
|
||||||
|
union CONFIG_REG {
|
||||||
|
struct VBIAS{
|
||||||
|
enum {
|
||||||
|
OFF = 0,
|
||||||
|
ON = 1
|
||||||
|
};
|
||||||
|
typedef BitField<uint8_t,7,1> Bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CONVERSION_MODE{
|
||||||
|
enum {
|
||||||
|
OFF = 0,
|
||||||
|
AUTO = 1
|
||||||
|
};
|
||||||
|
typedef BitField<uint8_t,6,1> Bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ONE_SHOT{
|
||||||
|
enum {
|
||||||
|
IDLE = 0,
|
||||||
|
SET = 1
|
||||||
|
};
|
||||||
|
typedef BitField<uint8_t,5,1> Bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WIRING{
|
||||||
|
enum {
|
||||||
|
TWO_OR_FOUR_WIRE = 0,
|
||||||
|
THREE_WIRE = 1
|
||||||
|
};
|
||||||
|
typedef BitField<uint8_t,4,1> Bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
enum {
|
||||||
|
IDLE = 0,
|
||||||
|
SET = 1
|
||||||
|
};
|
||||||
|
typedef BitField<uint8_t,5,1> Bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __MAX31865_HPP__
|
@ -0,0 +1,57 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "./driver/device.hpp"
|
||||||
|
#include "./utils/BitField.hpp"
|
||||||
|
|
||||||
|
#ifdef SIMPLE_TEST
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
std::cout << "test" << std::endl;
|
||||||
|
|
||||||
|
BitField<uint8_t, 1, 2> bitfield_0;
|
||||||
|
BitField<uint8_t, 5, 2> bitfield_1;
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "testing bitfield 0" << std::endl;
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < 10; i++) {
|
||||||
|
|
||||||
|
bitfield_0 = i;
|
||||||
|
std::cout << static_cast<uint32_t>(bitfield_0()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "testing bitfield 1" << std::endl;
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < 10; i++) {
|
||||||
|
|
||||||
|
bitfield_1 = i;
|
||||||
|
std::cout << static_cast<uint32_t>(bitfield_1()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Device dev();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
std::cout << "test" << std::endl;
|
||||||
|
|
||||||
|
//std::cout << std::hex << ((1ULL << 2)-1) << std::endl;
|
||||||
|
std::cout << 1ULL << std::endl;
|
||||||
|
|
||||||
|
Device dev;
|
||||||
|
|
||||||
|
//dev.doSomething();
|
||||||
|
|
||||||
|
dev.status();
|
||||||
|
|
||||||
|
//dev.doSomething();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -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,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_
|
Loading…
Reference in new issue