modm API documentation
General Purpose Registers

Classes

struct  modm::Configuration< Parent, Enum, Mask, Position >
 
struct  modm::Flags< Enum, T >
 
struct  modm::FlagsGroup< T... >
 
struct  modm::FlagsOperators< Enum, T >
 
struct  modm::Register< T >
 
struct  modm::Value< Parent, Width, Position >
 

Macros

#define MODM_FLAGS8(Enum)
 
#define MODM_FLAGS16(Enum)
 
#define MODM_FLAGS32(Enum)
 
#define MODM_TYPE_FLAGS(Parent)
 
#define MODM_FLAGS_CONFIG(Parent, Config)
 

Variables

modm::FlagsOperators modm::modm_packed
 
using modm::Register8 = Register< uint8_t >
 Register class with 8-bit wide underlying type.
 
using modm::Register16 = Register< uint16_t >
 Register class with 16-bit wide underlying type.
 
using modm::Register32 = Register< uint32_t >
 Register class with 32-bit wide underlying type.
 
template<typename Enum = uint8_t>
using modm::Flags8 = Flags< Enum, uint8_t >
 Flags class with 8-bit wide underlying type.
 
template<typename Enum = uint16_t>
using modm::Flags16 = Flags< Enum, uint16_t >
 Flags class with 16-bit wide underlying type.
 
template<typename Enum = uint32_t>
using modm::Flags32 = Flags< Enum, uint32_t >
 Flags class with 32-bit wide underlying type.
 

Detailed Description

lbuild module: modm:architecture:register

Data structures to provide a native register abstraction.

These data structures are used to describe the relationship of single bits, bit groups and bit configurations in registers with type-safe access.

Registers can be made up of three things:

Example of an 8-bit register called Control

7 6 5 4 3 2 1 0
| EN | FS | PRE1 | PRE0 | DEL2 | DEL1 | DEL0 | |

Register Bits

The bits can be modelled using strongly-typed enums and the Flags template class as follows:

enum class
Control : uint8_t
{
EN = Bit7, ///< bit documentation
FS = Bit6,
PRE1 = Bit5,
PRE0 = Bit4,
DEL2 = Bit3,
DEL1 = Bit2,
DEL0 = Bit1,
};
MODM_FLAGS8(Control);
// expands to
// typedef modm::Flags8< Control > Control_t;
// and some enum operator overloading magic

You can handle all its register bits as you would expect:

Control_t control = Control::EN;
control = Control::EN | Control::FS;
control &= ~Control::FS;
control |= Control::FS;
control ^= Control::PRE1;
bool isSet = control & Control::FS;
control.reset(Control::PRE1 | Control::PRE0);
control.set(Control::DEL0);
bool noneSet = control.none(Control::PRE1 | Control::PRE0);
bool allSet = control.all(Control::EN | Control::FS);

You still get raw access if you really need it:

uint8_t raw = control.value; // the underlying type
control.value = 0x24;

The access is type-safe, you cannot use bits from two different registers:

enum class Control2 : uint8_t
{
DIS = Bit4,
HS = Bit3,
};
MODM_FLAGS8(Control2);
auto control = Control::EN | Control2::HS; // compile error

You can even overload functions on argument type now:

void write(Control_t control);
void write(Control2_t control);
write(Control::EN | Control::FS); // calls #1
write(Control2::DIS); // calls #2

Register Configurations

Configurations are also described as a strongly-typed enum and then wrapped into the Configuration template class.

enum class
Prescaler : uint8_t
{
Div1 = 0, ///< configuration documentation
Div2 = int(Control::PRE0),
Div4 = int(Control::PRE1),
Div8 = int(Control::PRE1) | int(Control::PRE0),
};
typedef Configuration< Control_t, Prescaler, (Bit5 | Bit4) > Prescaler_t;

The Prescaler enum values are already shifted in this example (hence the (Bit5 | Bit4) mask), however you can also declare the prescaler values non-shifted and let the wrapper shift it:

enum class Prescaler : uint8_t
{
Div1 = 0,
Div2 = 1,
Div4 = 2,
Div8 = 3,
};
typedef Configuration<Control_t, Prescaler, 0b11, 4> Prescaler_t;

Why? If you have two or more configurations with the same selections in the same register, you can simply add another one:

typedef Configuration< Control_t, Prescaler, 0b11, 6 > Prescaler2_t;

Configurations can be used inline:

Control_t control = Control::EN | Prescaler_t(Prescaler::Div2);
Control_t control &= ~Prescaler_t::mask();

But do not have to:

Prescaler_t::set(control, Prescaler::Div2);
Prescaler_t::reset(control);
Prescaler prescaler = Prescaler_t::get(control);

Register Values

Values are described using the Value template class which masks and shifts the value as required. In our example the value has a width of 3 bits and needs to be shifted 1 bit:

typedef Value< Control_t, 3, 1 > Delay_t;

This can be used the same way as the Configuration:

Control_t control = Control::EN | Prescaler_t(Prescaler::Div2) | Delay_t(4);
Control_t control &= ~Delay_t::mask();
Delay_t::set(control, 7);
Delay_t::reset(control);
uint8_t delay = Delay_t::get(control);

See Typesafe Register Access in C++ for a more detailed background on this implementation.

Macro Definition Documentation

#define MODM_FLAGS16

This macro creates a Flags16 class with the enum class provided and adds the required bitwise (Enum op Enum) operator overloads for it. The resulting Flags16 class type will have the signature Enum_t.

Warning
This macro only works properly inside of a struct or class.
See also
MODM_TYPE_FLAGS
Parameters
Enuma strongly-typed enum containing the bit masks
#define MODM_FLAGS32

This macro creates a Flags32 class with the enum class provided and adds the required bitwise (Enum op Enum) operator overloads for it. The resulting Flags32 class type will have the signature Enum_t.

Warning
This macro only works properly inside of a struct or class.
See also
MODM_TYPE_FLAGS
Parameters
Enuma strongly-typed enum containing the bit masks
#define MODM_FLAGS8

This macro creates a Flags8 class with the enum class provided and adds the required bitwise (Enum op Enum) operator overloads for it The resulting Flags8 class type will have the signature Enum_t.

Warning
This macro only works properly inside of a struct or class.
See also
MODM_TYPE_FLAGS
Parameters
Enuma strongly-typed enum containing the bit masks
#define MODM_FLAGS_CONFIG

This macro creates a Config_t type out of the Parent and Config enum. The mask is taken from a Parent::Config_Mask field containing the ORed bits of the configuration.

Note
This macro does not allow using the configuration position. Please use the modm::Configuration class manually in that case.
Parameters
Parenta Flags Enum
Configa Config Enum
#define MODM_TYPE_FLAGS

This macro creates bitwise (Parent::EnumType op Parent::EnumType) operator overloads for use with the Flags class.

Warning
This macro only works properly outside of a struct or class.
Parameters
Parenta Flags class