Shared Assets

This file provides the assets shared between all library components.

namespace axmc_shared_assets

Provides all assets (structures, enumerations, functions) that are intended to be shared between library components.

Enums

enum class kCommunicationStatusCodes : uint8_t

Defines the codes used by the Communication class to indicate the status of all supported data manipulations.

Values:

enumerator kStandby

The default value used to initialize the communication_status variable.

enumerator kReceptionError

Communication class ran into an error when receiving a message.

enumerator kParsingError

Communication class ran into an error when parsing (reading) a message.

enumerator kPackingError

Communication class ran into an error when writing a message to payload.

enumerator kMessageSent

Communication class successfully sent a message.

enumerator kMessageReceived

Communication class successfully received a message.

enumerator kInvalidProtocol

The message protocol code is not valid for the type of operation (Rx or Tx).

enumerator kNoBytesToReceive

Communication class did not receive enough bytes to process the message.

enumerator kParameterMismatch

The size of the received parameters structure does not match expectation.

enumerator kParametersExtracted

Parameter data has been successfully extracted.

enumerator kExtractionForbidden

Attempted to extract parameters from the message other than ModuleParameters.

namespace axmc_communication_assets

Provides all assets (structures, enumerations, variables) used to support bidirectional communication with the host-computer (PC).

Warning

These assets are designed to be used internally by the core library classes. End users should not modify any assets from this namespace.

Enums

enum class kProtocols : uint8_t

Defines the protocol codes used by the Communication class to specify incoming and outgoing message layouts.

Values:

enumerator kUndefined

Not a valid protocol code. Used to initialize the Communication class.

enumerator KRepeatedModuleCommand

Used by Module-addressed commands that should be repeated (executed recurrently).

enumerator kOneOffModuleCommand

Used by Module-addressed commands that should not be repeated (executed only once).

enumerator kDequeueModuleCommand

Used by Module-addressed commands that remove all queued commands, including recurrent commands.

enumerator kKernelCommand

Used by Kernel-addressed commands. All Kernel commands are always non-repeatable (one-shot).

enumerator kModuleParameters

Used by Module-addressed parameter messages.

enumerator kModuleData

Used by Module data or error messages that include an arbitrary data object in addition to the event state-code.

enumerator kKernelData

Used by Kernel data or error messages that include an arbitrary data object in addition to event state-code.

enumerator kModuleState

Used by Module data or error messages that only include the state-code.

enumerator kKernelState

Used by Kernel data or error messages that only include the state-code.

enumerator kReceptionCode

Used to acknowledge the reception of command and parameter messages.

enumerator kControllerIdentification

Used to identify the host-microcontroller to the PC.

enumerator kModuleIdentification

Used to identify the hardware module instances managed by a Kernel instance to the PC.

enum class kPrototypes : uint8_t

Defines the prototype codes used by the Communication class to specify the layout of additional data objects transmitted by KernelData and ModuleData messages.

Warning

The data messages can only transmit the objects whose prototypes are defined in this enumeration.

Values:

enumerator kOneBool

1 8-bit boolean

enumerator kOneUint8

1 unsigned 8-bit integer

enumerator kOneInt8

1 signed 8-bit integer

enumerator kTwoBools

An array of 2 8-bit booleans.

enumerator kTwoUint8s

An array of 2 unsigned 8-bit integers.

enumerator kTwoInt8s

An array of 2 signed 8-bit integers.

enumerator kOneUint16

1 unsigned 16-bit integer

enumerator kOneInt16

1 signed 16-bit integer

enumerator kThreeBools

An array of 3 8-bit booleans.

enumerator kThreeUint8s

An array of 3 unsigned 8-bit integers.

enumerator kThreeInt8s

An array of 3 signed 8-bit integers.

enumerator kFourBools

An array of 4 8-bit booleans.

enumerator kFourUint8s

An array of 4 unsigned 8-bit integers.

enumerator kFourInt8s

An array of 4 signed 8-bit integers.

enumerator kTwoUint16s

An array of 2 unsigned 16-bit integers.

enumerator kTwoInt16s

An array of 2 signed 16-bit integers.

enumerator kOneUint32

1 unsigned 32-bit integer

enumerator kOneInt32

1 signed 32-bit integer

enumerator kOneFloat32

1 single-precision 32-bit floating-point number

enumerator kFiveBools

An array of 5 8-bit booleans.

enumerator kFiveUint8s

An array of 5 unsigned 8-bit integers.

enumerator kFiveInt8s

An array of 5 signed 8-bit integers.

enumerator kSixBools

An array of 6 8-bit booleans.

enumerator kSixUint8s

An array of 6 unsigned 8-bit integers.

enumerator kSixInt8s

An array of 6 signed 8-bit integers.

enumerator kThreeUint16s

An array of 3 unsigned 16-bit integers.

enumerator kThreeInt16s

An array of 3 signed 16-bit integers.

enumerator kSevenBools

An array of 7 8-bit booleans.

enumerator kSevenUint8s

An array of 7 unsigned 8-bit integers.

enumerator kSevenInt8s

An array of 7 signed 8-bit integers.

enumerator kEightBools

An array of 8 8-bit booleans.

enumerator kEightUint8s

An array of 8 unsigned 8-bit integers.

enumerator kEightInt8s

An array of 8 signed 8-bit integers.

enumerator kFourUint16s

An array of 4 unsigned 16-bit integers.

enumerator kFourInt16s

An array of 4 signed 16-bit integers.

enumerator kTwoUint32s

An array of 2 unsigned 32-bit integers.

enumerator kTwoInt32s

An array of 2 signed 32-bit integers.

enumerator kTwoFloat32s

An array of 2 single-precision 32-bit floating-point numbers.

enumerator kOneUint64

1 unsigned 64-bit integer

enumerator kOneInt64

1 signed 64-bit integer

enumerator kOneFloat64

1 double-precision 64-bit floating-point number

enumerator kNineBools

An array of 9 8-bit booleans.

enumerator kNineUint8s

An array of 9 unsigned 8-bit integers.

enumerator kNineInt8s

An array of 9 signed 8-bit integers.

enumerator kTenBools

An array of 10 8-bit booleans.

enumerator kTenUint8s

An array of 10 unsigned 8-bit integers.

enumerator kTenInt8s

An array of 10 signed 8-bit integers.

enumerator kFiveUint16s

An array of 5 unsigned 16-bit integers.

enumerator kFiveInt16s

An array of 5 signed 16-bit integers.

enumerator kElevenBools

An array of 11 8-bit booleans.

enumerator kElevenUint8s

An array of 11 unsigned 8-bit integers.

enumerator kElevenInt8s

An array of 11 signed 8-bit integers.

enumerator kTwelveBools

An array of 12 8-bit booleans.

enumerator kTwelveUint8s

An array of 12 unsigned 8-bit integers.

enumerator kTwelveInt8s

An array of 12 signed 8-bit integers.

enumerator kSixUint16s

An array of 6 unsigned 16-bit integers.

enumerator kSixInt16s

An array of 6 signed 16-bit integers.

enumerator kThreeUint32s

An array of 3 unsigned 32-bit integers.

enumerator kThreeInt32s

An array of 3 signed 32-bit integers.

enumerator kThreeFloat32s

An array of 3 single-precision 32-bit floating-point numbers.

enumerator kThirteenBools

An array of 13 8-bit booleans.

enumerator kThirteenUint8s

An array of 13 unsigned 8-bit integers.

enumerator kThirteenInt8s

An array of 13 signed 8-bit integers.

enumerator kFourteenBools

An array of 14 8-bit booleans.

enumerator kFourteenUint8s

An array of 14 unsigned 8-bit integers.

enumerator kFourteenInt8s

An array of 14 signed 8-bit integers.

enumerator kSevenUint16s

An array of 7 unsigned 16-bit integers.

enumerator kSevenInt16s

An array of 7 signed 16-bit integers.

enumerator kFifteenBools

An array of 15 8-bit booleans.

enumerator kFifteenUint8s

An array of 15 unsigned 8-bit integers.

enumerator kFifteenInt8s

An array of 15 signed 8-bit integers.

enumerator kEightUint16s

An array of 8 unsigned 16-bit integers.

enumerator kEightInt16s

An array of 8 signed 16-bit integers.

enumerator kFourUint32s

An array of 4 unsigned 32-bit integers.

enumerator kFourInt32s

An array of 4 signed 32-bit integers.

enumerator kFourFloat32s

An array of 4 single-precision 32-bit floating-point numbers.

enumerator kTwoUint64s

An array of 2 unsigned 64-bit integers.

enumerator kTwoInt64s

An array of 2 signed 64-bit integers.

enumerator kTwoFloat64s

An array of 2 double-precision 64-bit floating-point numbers.

enumerator kNineUint16s

An array of 9 unsigned 16-bit integers.

enumerator kNineInt16s

An array of 9 signed 16-bit integers.

enumerator kTenUint16s

An array of 10 unsigned 16-bit integers.

enumerator kTenInt16s

An array of 10 signed 16-bit integers.

enumerator kFiveUint32s

An array of 5 unsigned 32-bit integers.

enumerator kFiveInt32s

An array of 5 signed 32-bit integers.

enumerator kFiveFloat32s

An array of 5 single-precision 32-bit floating-point numbers.

enumerator kElevenUint16s

An array of 11 unsigned 16-bit integers.

enumerator kElevenInt16s

An array of 11 signed 16-bit integers.

enumerator kTwelveUint16s

An array of 12 unsigned 16-bit integers.

enumerator kTwelveInt16s

An array of 12 signed 16-bit integers.

enumerator kSixUint32s

An array of 6 unsigned 32-bit integers.

enumerator kSixInt32s

An array of 6 signed 32-bit integers.

enumerator kSixFloat32s

An array of 6 single-precision 32-bit floating-point numbers.

enumerator kThreeUint64s

An array of 3 unsigned 64-bit integers.

enumerator kThreeInt64s

An array of 3 signed 64-bit integers.

enumerator kThreeFloat64s

An array of 3 double-precision 64-bit floating-point numbers.

enumerator kThirteenUint16s

An array of 13 unsigned 16-bit integers.

enumerator kThirteenInt16s

An array of 13 signed 16-bit integers.

enumerator kFourteenUint16s

An array of 14 unsigned 16-bit integers.

enumerator kFourteenInt16s

An array of 14 signed 16-bit integers.

enumerator kSevenUint32s

An array of 7 unsigned 32-bit integers.

enumerator kSevenInt32s

An array of 7 signed 32-bit integers.

enumerator kSevenFloat32s

An array of 7 single-precision 32-bit floating-point numbers.

enumerator kFifteenUint16s

An array of 15 unsigned 16-bit integers.

enumerator kFifteenInt16s

An array of 15 signed 16-bit integers.

enumerator kEightUint32s

An array of 8 unsigned 32-bit integers.

enumerator kEightInt32s

An array of 8 signed 32-bit integers.

enumerator kEightFloat32s

An array of 8 single-precision 32-bit floating-point numbers.

enumerator kFourUint64s

An array of 4 unsigned 64-bit integers.

enumerator kFourInt64s

An array of 4 signed 64-bit integers.

enumerator kFourFloat64s

An array of 4 double-precision 64-bit floating-point numbers.

enumerator kNineUint32s

An array of 9 unsigned 32-bit integers.

enumerator kNineInt32s

An array of 9 signed 32-bit integers.

enumerator kNineFloat32s

An array of 9 single-precision 32-bit floating-point numbers.

enumerator kTenUint32s

An array of 10 unsigned 32-bit integers.

enumerator kTenInt32s

An array of 10 signed 32-bit integers.

enumerator kTenFloat32s

An array of 10 single-precision 32-bit floating-point numbers.

enumerator kFiveUint64s

An array of 5 unsigned 64-bit integers.

enumerator kFiveInt64s

An array of 5 signed 64-bit integers.

enumerator kFiveFloat64s

An array of 5 double-precision 64-bit floating-point numbers.

enumerator kElevenUint32s

An array of 11 unsigned 32-bit integers.

enumerator kElevenInt32s

An array of 11 signed 32-bit integers.

enumerator kElevenFloat32s

An array of 11 single-precision 32-bit floating-point numbers.

enumerator kTwelveUint32s

An array of 12 unsigned 32-bit integers.

enumerator kTwelveInt32s

An array of 12 signed 32-bit integers.

enumerator kTwelveFloat32s

An array of 12 single-precision 32-bit floating-point numbers.

enumerator kSixUint64s

An array of 6 unsigned 64-bit integers.

enumerator kSixInt64s

An array of 6 signed 64-bit integers.

enumerator kSixFloat64s

An array of 6 double-precision 64-bit floating-point numbers.

enumerator kThirteenUint32s

An array of 13 unsigned 32-bit integers.

enumerator kThirteenInt32s

An array of 13 signed 32-bit integers.

enumerator kThirteenFloat32s

An array of 13 single-precision 32-bit floating-point numbers.

enumerator kFourteenUint32s

An array of 14 unsigned 32-bit integers.

enumerator kFourteenInt32s

An array of 14 signed 32-bit integers.

enumerator kFourteenFloat32s

An array of 14 single-precision 32-bit floating-point numbers.

enumerator kSevenUint64s

An array of 7 unsigned 64-bit integers.

enumerator kSevenInt64s

An array of 7 signed 64-bit integers.

enumerator kSevenFloat64s

An array of 7 double-precision 64-bit floating-point numbers.

enumerator kFifteenUint32s

An array of 15 unsigned 32-bit integers.

enumerator kFifteenInt32s

An array of 15 signed 32-bit integers.

enumerator kFifteenFloat32s

An array of 15 single-precision 32-bit floating-point numbers.

enumerator kEightUint64s

An array of 8 unsigned 64-bit integers.

enumerator kEightInt64s

An array of 8 signed 64-bit integers.

enumerator kEightFloat64s

An array of 8 double-precision 64-bit floating-point numbers.

enumerator kNineUint64s

An array of 9 unsigned 64-bit integers.

enumerator kNineInt64s

An array of 9 signed 64-bit integers.

enumerator kNineFloat64s

An array of 9 double-precision 64-bit floating-point numbers.

enumerator kTenUint64s

An array of 10 unsigned 64-bit integers.

enumerator kTenInt64s

An array of 10 signed 64-bit integers.

enumerator kTenFloat64s

An array of 10 double-precision 64-bit floating-point numbers.

enumerator kElevenUint64s

An array of 11 unsigned 64-bit integers.

enumerator kElevenInt64s

An array of 11 signed 64-bit integers.

enumerator kElevenFloat64s

An array of 11 double-precision 64-bit floating-point numbers.

enumerator kTwelveUint64s

An array of 12 unsigned 64-bit integers.

enumerator kTwelveInt64s

An array of 12 signed 64-bit integers.

enumerator kTwelveFloat64s

An array of 12 double-precision 64-bit floating-point numbers.

enumerator kThirteenUint64s

An array of 13 unsigned 64-bit integers.

enumerator kThirteenInt64s

An array of 13 signed 64-bit integers.

enumerator kThirteenFloat64s

An array of 13 double-precision 64-bit floating-point numbers.

enumerator kFourteenUint64s

An array of 14 unsigned 64-bit integers.

enumerator kFourteenInt64s

An array of 14 signed 64-bit integers.

enumerator kFourteenFloat64s

An array of 14 double-precision 64-bit floating-point numbers.

enumerator kFifteenUint64s

An array of 15 unsigned 64-bit integers.

enumerator kFifteenInt64s

An array of 15 signed 64-bit integers.

enumerator kFifteenFloat64s

An array of 15 double-precision 64-bit floating-point numbers.

struct DequeueModuleCommand
#include <axmc_shared_assets.h>

Instructs the addressed Module instance to clear (empty) its command queue.

Public Members

uint8_t module_type = 0

The type (family) code of the module to which the command is addressed.

uint8_t module_id = 0

The ID of the specific module instance within the broader module family.

uint8_t return_code = 0

The code to use for acknowledging the reception of the message, if set to a non-zero value.

struct KernelCommand
#include <axmc_shared_assets.h>

Instructs the Kernel to run the specified command exactly once.

Public Members

uint8_t return_code = 0

The code to use for acknowledging the reception of the message, if set to a non-zero value.

uint8_t command = 0

The code of the command to execute.

struct KernelData
#include <axmc_shared_assets.h>

Communicates that the Kernel has encountered a notable event and includes an additional data object.

Note

Use the KernelState structure for messages that only need to transmit an event state-code.

Public Members

uint8_t protocol

The message protocol used by this structure.

uint8_t command

The command the Kernel was executing when it sent the data message.

uint8_t event

The event that prompted the data transmission.

uint8_t prototype

The code that specifies the type of the data object transmitted with the message.

struct KernelState
#include <axmc_shared_assets.h>

Communicates that the Kernel has encountered a notable event.

Note

Use the KernelData structure for messages that need to transmit a data object in addition to the state event-code.

Public Members

uint8_t protocol

The message protocol used by this structure.

uint8_t command

The command the Kernel was executing when it sent the data message.

uint8_t event

The event that prompted the data transmission.

struct ModuleData
#include <axmc_shared_assets.h>

Communicates that the Module has encountered a notable event and includes an additional data object.

Note

Use the ModuleState structure for messages that only need to transmit an event state-code.

Public Members

uint8_t protocol

The message protocol used by this structure.

uint8_t module_type

The type (family) code of the module that sent the data message.

uint8_t module_id

The ID of the specific module instance within the broader module family.

uint8_t command

The command the Module was executing when it sent the data message.

uint8_t event

The event that prompted the data transmission.

uint8_t prototype

The code that specifies the type of the data object transmitted with the message.

struct ModuleParameters
#include <axmc_shared_assets.h>

Instructs the addressed Module instance to update its parameters with the included data.

Public Members

uint8_t module_type = 0

The type (family) code of the module to which the parameter configuration is addressed.

uint8_t module_id = 0

The ID of the specific module instance within the broader module family.

uint8_t return_code = 0

The code to use for acknowledging the reception of the message, if set to a non-zero value.

struct ModuleState
#include <axmc_shared_assets.h>

Communicates that the Module has encountered a notable event.

Note

Use the ModuleData structure for messages that need to transmit a data object in addition to the state event-code.

Public Members

uint8_t protocol

The message protocol used by this structure.

uint8_t module_type

The type (family) code of the module that sent the data message.

uint8_t module_id

The ID of the specific module instance within the broader module family.

uint8_t command

The command the Module was executing when it sent the data message.

uint8_t event

The event that prompted the data transmission.

struct OneOffModuleCommand
#include <axmc_shared_assets.h>

Instructs the addressed Module instance to run the specified command exactly once (non-recurrently).

Public Members

uint8_t module_type = 0

The type (family) code of the module to which the command is addressed.

uint8_t module_id = 0

The ID of the specific module instance within the broader module family.

uint8_t return_code = 0

The code to use for acknowledging the reception of the message, if set to a non-zero value.

uint8_t command = 0

The code of the command to execute.

bool noblock = false

Determines whether to allow concurrent execution of other commands while waiting for the requested command to complete.

struct RepeatedModuleCommand
#include <axmc_shared_assets.h>

Instructs the addressed Module instance to run the specified command repeatedly (recurrently).

Public Members

uint8_t module_type = 0

The type (family) code of the module to which the command is addressed.

uint8_t module_id = 0

The ID of the specific module instance within the broader module family.

uint8_t return_code = 0

The code to use for acknowledging the reception of the message, if set to a non-zero value.

uint8_t command = 0

The code of the command to execute.

bool noblock = false

Determines whether to allow concurrent execution of other commands while waiting for the requested command to complete.

uint32_t cycle_delay = 0

The delay, in microseconds, before repeating (cycling) the command.

Communication

Provides the Communication class that establishes and maintains bidirectional communication with host-computers (PCs) running the ataraxis-communication-interface Python library.

Description:

This class defines the communication message structures and provides the API used by other library components to exchange data with the interface running on the PC.

Note

A single shared instance of this class should be created inside the main.cpp file and provided as an initialization argument to the Kernel instance and all Module-derived instances.

class Communication
#include <communication.h>

Exposes methods that allow exchanging data with a host-computer (PC) running the ataraxis-communication-interface library.

Warning

This class is explicitly designed to be used by other library assets and should not be used directly by end users. A single shared instance of this class must be provided to the Kernel and all Module-derived classes as initialization arguments.

Public Functions

inline explicit Communication(Stream &communication_port)

Instantiates a specialized TransportLayer instance to handle the microcontroller-PC communication.

Example instantiation:

Serial.begin(9600);  // Initializes the serial communication interface.
Communication comm_class(Serial);  // Instantiates the Communication class.

Warning

This class reserves up to ~1kB of RAM during runtime. On supported lower-end microcontrollers this number may be lowered up to ~700 bytes due to adaptive optimization.

Parameters:

communication_port – The initialized communication interface instance, such as Serial or USB Serial.

inline uint8_t GetTransportLayerStatus() const

Returns the most recent TransportLayer’s status code.

template<typename ObjectType>
inline bool SendDataMessage(const uint8_t module_type, const uint8_t module_id, const uint8_t command, const uint8_t event_code, const kPrototypes prototype, const ObjectType &object)

Sends the input event code and data object to the PC.

Example usage:

Communication comm_class(Serial);  // Instantiates the Communication class.
Serial.begin(9600);  // Initializes serial interface.

// Sends the example data message.
const uint8_t module_type = 112
const uint8_t module_id = 12;
const uint8_t command = 88;
const uint8_t event_code = 221;
auto prototype = kPrototypes::kOneUint8;
const uint8_t placeholder_object = 255;
comm_class.SendDataMessage(module_type, module_id, command, event_code, prototype, placeholder_object);

Warning

Use the SendStateMessage() method to communicate the event-code without any additional data for faster transmission.

Template Parameters:

ObjectType – The type of the data object to be sent along with the message.

Parameters:
  • module_type – The type of the module that sent the message.

  • module_id – The ID of the specific module instance that sent the message.

  • command – The command executed by the module that sent the message.

  • event_code – The event that triggered the message.

  • prototype – The type of the data object transmitted with the message. Must be one of the kPrototypes enumeration members.

  • object – The data object to be sent along with the message.

Returns:

True if the message is sent, false otherwise.

template<typename ObjectType>
inline bool SendDataMessage(const uint8_t command, const uint8_t event_code, const kPrototypes prototype, const ObjectType &object)

Overloads SendDataMessage to support sending Kernel data messages.

inline bool SendStateMessage(const uint8_t module_type, const uint8_t module_id, const uint8_t command, const uint8_t event_code)

Sends the input event code to the PC.

Example usage:

Communication comm_class(Serial);  // Instantiates the Communication class.
Serial.begin(9600);  // Initializes serial interface.

// Sends the example state message.
const uint8_t module_type = 112;
const uint8_t module_id = 12;
const uint8_t command = 88;
const uint8_t event_code = 221;
comm_class.SendStateMessage(module_type, module_id, command, event_code);

Note

Use the SendDataMessage() method to send a message with an additional arbitrary data object.

Parameters:
  • module_type – The type of the module that sent the message.

  • module_id – The ID of the specific module instance that sent the message.

  • command – The command executed by the module that sent the message.

  • event_code – The event that triggered the message.

Returns:

True if the message is sent, false otherwise.

inline bool SendStateMessage(const uint8_t command, const uint8_t event_code)

Overloads SendDataMessage to support sending Kernel state messages.

inline void SendCommunicationErrorMessage(const uint8_t module_type, const uint8_t module_id, const uint8_t command, const uint8_t error_code)

Sends the communication error message to the PC and activates the built-in LED.

Warning

This method is reserved for Communication class errors. Use SendDataMessage and SendStateMessage methods for all other errors.

Parameters:
  • module_type – The type of the module that sent the message.

  • module_id – The ID of the specific module instance that sent the message.

  • command – The command executed by the module that sent the message.

  • error_code – The encountered communication error.

inline void SendCommunicationErrorMessage(const uint8_t command, const uint8_t error_code)

Overloads SendCommunicationErrorMessage to support sending Kernel communication error messages.

template<const kProtocols protocol, typename ObjectType>
inline bool SendServiceMessage(const ObjectType service_code)

Uses the specified service message protocol to send the input service code to the PC.

Example usage:

Communication comm_class(Serial);  // Instantiates the Communication class.
Serial.begin(9600);  // Initializes serial interface.

// Protocol is given as a template, service code as an uint8_t argument.
comm_class.SendServiceMessage<kProtocols::kReceptionCode>(112);

Template Parameters:
  • protocol – The protocol to use for the transmitted message. Has to be one of the following kProtocols enumeration members: kReceptionCode, kControllerIdentification or kModuleIdentification.

  • ObjectType – The data type of the service code value.

Parameters:

service_code – The service code to be transmitted to the PC.

Returns:

True if the message is sent, false otherwise.

inline bool ReceiveMessage()

If a message is currently stored in the serial interface’s reception buffer, moves it into the instance’s reception buffer.

Depending on the protocol used by the received message, the message header data is read into the appropriate instance’s attribute structure.

Example usage:

Serial.begin(9600);  // Initializes serial interface.
Communication comm_class(Serial);  // Instantiates the Communication class.
bool success = comm_class.ReceiveMessage();  // Attempts to receive the message
Attention

If the received message is a ModuleParameters message, call the ExtractModuleParameters() method to extract the data payload. This method DOES NOT extract Module parameter data from the serial buffer.

Returns:

True if a message was successfully received, false otherwise. If this method returns false, this does not by itself indicate a runtime error. Use the ‘communication_status’ instance property to determine if the method encountered a runtime error.

template<typename ObjectType, const size_t object_size = sizeof(ObjectType)>
inline bool ExtractModuleParameters(ObjectType &destination)

Extracts the parameter data payload transmitted with the last received ModuleParameters message into the destination object’s memory.

Example usage:

Serial.begin(9600);  // Initializes serial interface.
Communication comm_class(Serial);  // Instantiates the Communication class.

// Initializes a test structure.
struct DataMessage
{
    uint8_t id = 1;
    uint8_t data = 10;
} data_message;

bool success = comm_class.ExtractParameters(data_message);  // Attempts to extract the parameters.

Warning

This method is intended to be called by end users as part of the SetCustomParameters() virtual method implementation. Do not call this method from any other context.

Template Parameters:
  • ObjectType – The type of the destination object.

  • object_size – The size of the destination object, in bytes.

Parameters:

destination – The object where to unpack the received parameters. Typically, this is a packed structure.

Returns:

True if the parameter data was successfully extracted into the destination object and false otherwise.

Public Members

uint8_t communication_status = static_cast<uint8_t>(kCommunicationStatusCodes::kStandby)

Stores the runtime status of the most recently called method.

uint8_t protocol_code = static_cast<uint8_t>(kProtocols::kUndefined)

Stores the protocol code of the last received message.

RepeatedModuleCommand repeated_module_command

Stores the last received Module-addressed recurrent (repeated) command message data.

OneOffModuleCommand one_off_module_command

Stores the last received Module-addressed non-recurrent (one-off) command message data.

KernelCommand kernel_command

Stores the last received Kernel-addressed command message data.

DequeueModuleCommand module_dequeue

Stores the last received Module-addressed dequeue command message data.

ModuleParameters module_parameters_header

Stores the last received Module-addressed parameters message header data.

Private Members

TransportLayer<uint16_t, kMaximumPayloadSize, kMaximumPayloadSize> _transport_layer

The TransportLayer instance that handles the bidirectional communication with the PC.

Private Static Attributes

static uint8_t kMaximumPayloadSize = min(kSerialBufferSize - 6, 254)

The maximum possible size for the received and transmitted payloads. Reuses the kSerialBufferSize constant defined inside transport_layer.h to determine the serial buffer size of the host microcontroller.

namespace axtlmc_shared_assets

Kernel

Provides the Kernel class used to manage the runtime of custom hardware modules and integrate them with the companion host-computer (PC) control interface.

Description:

This class manages PC-microcontroller communication and schedules and executes commands addressed to custom hardware modules. Due to the static API exposed by the (base) Module class, from which all custom module instances should inherit, Kernel seamlessly integrates custom hardware modules with the centralized interface running on the host-computer (PC).

Note

A single instance of this class should be created in the main.cpp file and used to manage the runtime. See the example .cpp files included with the distribution of the library or the https://github.com/Sun-Lab-NBB/ataraxis-micro-controller repository for details.

class Kernel
#include <kernel.h>

Manages the runtime of one or more custom hardware module instances.

The Kernel integrates all custom hardware module instances with the centralized control interface running on the companion host-computer (PC). It handles the majority of the microcontroller-PC interactions.

Example Instantiation:

Communication axmc_communication(Serial);  // Communication class first
TestModule test_module(1, 1, axmc_communication);  // Example custom module
Module* modules[] = {&test_module};  // Packages the module(s) into an array to be provided to the Kernel class

// The Kernel class should always be instantiated last
const uint8_t controller_id = 123;  // Example controller ID
const uin32_t keepalive_interval = 1000;  // Example keepalive interval (1 second)
Kernel kernel_instance(controller_id, axmc_communication, modules, keepalive_interval);

Note

During initialization, this class should be provided with an array of hardware module instances that inherit from the Module class.

Warning

After initialization, call the instance’s Setup() method in the main setup() function and the RuntimeCycle() method in the main loop() function of the main.cpp / main.ino file.

Public Types

enum class kKernelStatusCodes : uint8_t

Defines the codes used by the Kernel class to communicate its runtime state to the PC.

Values:

enumerator kStandBy

Currently not used. Statically reserves 0 to NOT be a valid code.

enumerator kSetupComplete

Setup() method runtime succeeded.

enumerator kModuleSetupError

Setup() method runtime failed due to a module setup error.

enumerator kReceptionError

Encountered a communication error when receiving data from the PC.

enumerator kTransmissionError

Encountered a communication error when sending data to the PC.

enumerator kInvalidMessageProtocol

Received a message that uses an unsupported (unknown) protocol.

enumerator kModuleParametersSet

Received and applied the parameters addressed to the module instance.

enumerator kModuleParametersError

Unable to apply the received parameters to the module instance.

enumerator kCommandNotRecognized

Received an unsupported (unknown) Kernel command.

enumerator kTargetModuleNotFound

Unable to find the module with the requested combined type and ID code.

enumerator kKeepAliveTimeout

The Kernel did not receive a keepalive message within the expected time.

enum class kKernelCommands : uint8_t

Defines the codes for the supported Kernel’s commands.

Values:

enumerator kStandby

The standby code used during class initialization.

enumerator kReceiveData

Checks and, if possible, receives PC-sent data. Not externally addressable.

enumerator kResetController

Resets the software and hardware state of all managed assets.

enumerator kIdentifyController

Sends the ID of the controller to the PC.

enumerator kIdentifyModules

Sequentially sends each managed module’s combined Type+ID code to the PC.

enumerator kKeepAlive

Resets the keepalive watchdog timer, starting a new keepalive cycle.

Public Functions

template<const size_t kModuleNumber>
inline Kernel(const uint8_t controller_id, Communication &communication, Module *(&module_array)[kModuleNumber], const uint32_t keepalive_interval = 0)

Initializes the necessary assets used to manage the runtime of the input hardware module instances.

Parameters:
  • controller_id – The unique identifier of the microcontroller that uses this Kernel instance. This ID code has to be unique for all microcontrollers used at the same time.

  • communication – The shared Communication instance used to bidirectionally communicate with the PC during runtime.

  • module_array – The array of pointers to custom hardware module instances. Note, each instance must inherit from the base Module class.

  • keepalive_interval – The interval, in milliseconds, within which the Kernel must receive a keepalive command from the PC to prevent emergency shutdown. Setting this parameter to 0 disables the keepalive mechanism.

inline void Setup()

Configures the hardware and software assets used by the Kernel and all managed hardware modules.

Note

This method has to be called as part of the main setup() function.

Warning

This is the only method that turns off the built-in LED of the controller board. Seeing the LED constantly ON (HIGH) after this method’s runtime means the controller experienced a communication error when it tried sending data to the PC. Seeing the LED blinking with ~2-second periodicity indicates that the Kernel failed the setup sequence.

inline void RuntimeCycle()

Carries out a single runtime cycle.

During each runtime cycle, the instance first receives and processes all messages sent from the PC. All messages other than commands addressed to the managed hardware modules are processed and handled immediately. For example, Kernel-addressed commands are executed as soon as they are received. Module-addressed commands are queued for execution and are executed after all available data is received and parsed.

Once all data is received, the method loops over managed modules and executes one command execution stage for each module.

Note

This method has to be repeatedly called as part of the main loop() function.

Public Members

uint8_t kernel_command = static_cast<uint8_t>(kKernelCommands::kStandby)

Tracks the currently active Kernel command. This is used to send data and error messages to the PC.

Private Functions

inline uint8_t ReceiveData() const

If a message sent from the PC is available for reception, decodes it into the Communication’s reception buffer.

Returns:

The protocol code of the received message or 0 to indicate that no valid message was received.

template<typename ObjectType>
inline void SendData(const uint8_t event_code, const kPrototypes prototype, const ObjectType &object)

Packages and sends the provided event_code and data object to the PC.

Note

If the message is intended to communicate only the event code, do not provide the prototype or the data object. SendData() has an overloaded version specialized for sending event codes that is more efficient than the data-containing version.

Warning

If sending the data fails for any reason, this method automatically emits an error message. Since that error message may itself fail to be sent, the method also statically activates the built-in LED of the board to visually communicate the encountered runtime error. Do not use the LED-connected pin or LED when using this method to avoid interference!

Template Parameters:

ObjectType – The type of the data object to be sent along with the message.

Parameters:
  • event_code – The event that triggered the data transmission.

  • prototype – The type of the data object transmitted with the message. Must be one of the kPrototypes enumeration members.

  • object – The data object to be sent along with the message.

inline void SendData(const uint8_t event_code) const

Packages and sends the provided event code to the PC.

This method overloads the SendData() method to optimize transmitting messages that only need to communicate the event.

Parameters:

event_code – The code of the event that triggered the data transmission.

inline void SendControllerID() const

Sends the unique identifier code of the microcontroller that uses this Kernel instance to the PC.

inline void SendModuleTypeIDs() const

Sequentially sends the combined type and ID code for each hardware module instance managed by this Kernel instance to the PC.

inline void SendReceptionCode(const uint8_t reception_code) const

Sends the input reception code to the PC.

Parameters:

reception_code – The reception code received as part of an incoming message sent from the PC.

inline void SetupKernel()

Sets up the hardware and software assets managed by the Kernel class.

inline void RunKernelCommand()

Resolves and calls the method associated with the currently active Kernel command.

inline int16_t ResolveTargetModule(const uint8_t target_type, const uint8_t target_id)

Finds the managed hardware module instance addressed by the input type and id codes.

Note

If this method is unable to resolve the target module, it automatically sends an error message to the PC in addition to returning the ‘-1’ error code.

Parameters:
  • target_type – The type (family) identifier of the addressed module.

  • target_id – The unique identifier of the addressed module.

Returns:

A non-negative integer representing the index of the module in the array of managed modules if the addressed module is found. A ‘-1’ value if the target module was not found.

inline void RunModuleCommands() const

Resolves and, if necessary, executes the active command for each managed hardware module.

Private Members

Module **_modules

Stores the managed custom hardware module classes.

const size_t _module_count

Stores the size of the _modules array.

const uint8_t _controller_id

Stores the unique identifier code of the microcontroller that uses the Kernel instance.

const uint32_t _keepalive_interval

Stores the maximum period of time, in milliseconds, that can separate two consecutive keepalive messages sent from the PC to the microcontroller.

elapsedMillis _since_previous_keepalive

The elapsedMillis instance that tracks the time elapsed since receiving the last keepalive message.

bool _keepalive_enabled = false

Tracks whether the keepalive tracking is enabled.

Communication &_communication

The Communication instance used to bidirectionally communicate with the PC interface.

bool _setup_complete = false

Tracks whether the Setup() method has been called to ensure that the instance is properly configured for runtime.

Module

Provides the Module class that exposes the API for integrating user-defined custom hardware modules with other library components and the interface running on the host-computer (PC).

Description:

This class defines the API interface used by Kernel and Communication classes to interact with any custom hardware module instance that inherits from the base Module class. Additionally, the class provides the utility functions for routine tasks, such as changing pin states, that support the concurrent (non-blocking) runtime of multiple module-derived instances.

Attention

Every custom hardware module class should inherit from the base Module class defined in this file and override the pure virtual methods of the parent class with instance-specific implementations.

class Module
#include <module.h>

Provides the API used by other library components to integrate any custom hardware module class with the interface running on the companion host-computer (PC).

Any class that inherits from this base class gains the API used by the Kernel and Communication classes to enable bidirectionally interfacing with the module via the interface running on the companion host-computer (PC)

Note

Use the utility methods inherited from the base Module class and stage-based command design pattern to ensure that the custom module implementation is compatible with non-blocking runtime mode. See the ReadMe for more information about non-blocking runtime support.

Warning

Every custom module class has to inherit from this base class. Follow this instantiation order when writing the main .cpp / .ino file for the controller: CommunicationModule(s)Kernel. See the /examples folder for details.

Public Types

enum class kCoreStatusCodes : uint8_t

Defines the status codes used to communicate the states and errors encountered during the shared API method runtimes.

Attention

This enumeration only covers status codes used by non-virtual methods inherited from the base Module class. These status codes are considered ‘system-reserved’ and are handled implicitly by the PC-side companion library.

Note

To support consistent status code reporting, this enumeration reserves values 0 through 50. All custom status codes should use values 51 through 250. This prevents the status codes derived from this enumeration from clashing with custom status codes.

Values:

enumerator kStandBy

The code used to initialize the module_status variable.

enumerator kTransmissionError

Encountered an error when sending data to the PC.

enumerator kCommandCompleted

The last active command has been completed and removed from the queue.

enumerator kCommandNotRecognized

The RunActiveCommand() method did not recognize the requested command.

Public Functions

inline Module(const uint8_t module_type, const uint8_t module_id, Communication &communication)

Initializes all shared assets used to integrate the module with the rest of the library components.

Warning

This initializer must be called as part of the custom module’s initialization sequence for each module that subclasses this base class.

Parameters:
  • module_type – The code that identifies the type (family) of the module. All instances of the same custom module class should share this ID code.

  • module_id – The code that identifies the specific module instance. This code must be unique for each instance of the same module family (class) used as part of the same runtime.

  • communication – The shared Communication instance used to bidirectionally communicate with the PC during runtime.

inline void QueueCommand(const uint8_t command, const bool noblock, const uint32_t cycle_delay)

Queues the input command to be executed by the Module during the next runtime cycle iteration.

Warning

If the module already has a queued command, this method replaces that command with the input command data.

Parameters:
  • command – The command to execute.

  • noblock – Determines whether the queued command should run in blocking or non-blocking mode.

  • cycle_delay – The delay, in microseconds, before repeating (cycling) the command. Only provide this argument when queueing a recurrent command.

inline void QueueCommand(const uint8_t command, const bool noblock)

Overloads the QueueCommand() method for queueing non-cyclic commands.

inline void ResetCommandQueue()

Resets the module’s command queue.

Note

Calling this method does not abort already running commands: they are allowed to finish gracefully.

inline bool ResolveActiveCommand()

If possible, ensures that the module has an active command to execute.

Note

Uses the following order of preference to activate (execute) a command: finish already running commands > run new commands > repeat a previously executed recurrent command. When repeating recurrent commands, the method ensures the recurrent timeout has expired before reactivating the command.

Returns:

bool true if the module has a command to execute and false otherwise.

inline void ResetExecutionParameters()

Resets the module’s command queue and aborts any currently running commands.

inline uint8_t GetModuleID() const

Returns the ID of the instance.

inline uint8_t GetModuleType() const

Returns the type (family ID) of the instance.

inline uint16_t GetModuleTypeID() const

Returns the combined type and id value of the instance.

inline void SendCommandActivationError() const

Sends an error message to notify the PC that the instance did not recognize the active command.

virtual bool SetCustomParameters() = 0

Overwrites the memory of the object used to store the instance’s runtime parameters with the data received from the PC.

Example method implementation:

uint8_t custom_parameters_object[3] = {}; // Assume this object was created at class instantiation.

// Reads the data and returns the operation status to the caller (Kernel).
return ExtractParameters(custom_parameters_object);

Note

This method should call the ExtractParameters() method inherited from the base Module class to unpack the received custom parameters message into the structure (object) used to store the instance’s custom runtime parameters.

Returns:

bool true if new parameters were parsed successfully and false otherwise.

virtual bool RunActiveCommand() = 0

Executes the instance method associated with the active command.

Example method implementation:

uint8_t active_command = GetActiveCommand();  // Returns the code of the active command.

// Matches the active command to the appropriate method call.
switch (active_command) {
 case 1:
     command_1();
     return true; // This returns value means the command was recognized, not that it succeeded!
 case 2:
     bool success = command_2(11);
     if (success) command_3();
     return true;
 default:
     // If the command is not recognized, returns 'false'
     return false;
}

Note

This method should translate the active command returned by the GetActiveCommand() method inherited from the base Module class into the call to the command-specific method that executes the command’s logic.

Warning

This method should not evaluate whether the command ran successfully, only whether the command was recognized and matched to the appropriate method call. The called method should use the inherited SendData() method to report command runtime status to the PC.

Returns:

bool true if the active module command was matched to a specific custom method and false otherwise.

virtual bool SetupModule() = 0

Sets up the instance’s hardware and software assets.

Example method implementation:

// Resets custom software assets:
uint8_t custom_parameters_object[3] = {5, 5, 5}; // Assume this object was created at class instantiation.
custom_parameters_object[0] = 0;  // Reset the first byte of the object to zero.
custom_parameters_object[1] = 0;  // Reset the second byte of the object to zero.
custom_parameters_object[2] = 0;  // Reset the third byte of the object to zero.

// Resets hardware assets:
const uint8_t output_pin = 12;
pinMode(output_pin, OUTPUT);  // Sets the output pin as output.
return true;
Attention

Ideally, this method should not contain any logic that can fail or block, as this method is called as part of the initial library runtime setup procedure, before the communication interface is fully initialized.

Note

This method should set the initial (default) state of the instance’s custom parameter structures and hardware (pins, timers, etc.).

Returns:

bool true if the setup method ran successfully and false otherwise.

virtual ~Module() = default

Destroys the instance during cleanup.

Public Members

struct Module::ExecutionControlParameters execution_parameters

Stores instance-specific runtime flow control parameters.

Protected Functions

inline uint8_t GetActiveCommand() const

Returns the active (running) command’s code or 0, if there are no active commands.

inline void AbortCommand()

Terminates the active command (if any).

If the aborted command is a recurrent command, the method resets the command queue to ensure that the command is not reactivated until it is re-queued from the PC.

inline void AdvanceCommandStage()

Advances the stage of the currently executed command.

As part of its runtime, the method also resets the stage delay timer, making it a one-stop solution for properly transitioning between command stages.

inline uint8_t GetCommandStage() const

Returns the execution stage of the active (running) command or 0, if there are no active commands.

inline void CompleteCommand()

Completes (ends) the active (running) command’s execution.

Note

It is essential that this method is called at the end of every command’s method (function) to allow executing other commands. Failure to do so can completely deadlock the Module and, in severe cases, the entire Microcontroller.

Warning

Only call this method when the command has completed everything it needed to do. To transition between the stages of the same command, use the AdvanceCommandStage() method instead.

inline bool WaitForMicros(const uint32_t delay_duration) const

Delays the active command execution for the requested number of microseconds.

Note

Depending on the active command’s configuration, the method can block in-place until the delay has passed or function as a non-blocking check for whether the required duration of microseconds has passed.

Warning

The delay is timed relative to the last command’s execution stage advancement.

Parameters:

delay_duration – The delay duration, in microseconds.

template<typename ObjectType = void>
inline void SendData(const uint8_t event_code, const kPrototypes prototype, const ObjectType &object)

Packages and sends the provided event_code and data object to the PC.

Note

If the message is intended to communicate only the event code, do not provide the prototype or the data object. SendData() has an overloaded version specialized for sending event codes that is more efficient than the data-containing version.

Warning

If sending the data fails for any reason, this method automatically emits an error message. Since that error message may itself fail to be sent, the method also statically activates the built-in LED of the board to visually communicate the encountered runtime error. Do not use the LED-connected pin or LED when using this method to avoid interference!

Template Parameters:

ObjectType – The type of the data object to be sent along with the message.

Parameters:
  • event_code – The event that triggered the data transmission.

  • prototype – The type of the data object transmitted with the message. Must be one of the kPrototypes enumeration members.

  • object – The data object to be sent along with the message.

inline void SendData(const uint8_t event_code) const

Packages and sends the provided event code to the PC.

This method overloads the SendData() method to optimize transmitting messages that only need to communicate the event.

Parameters:

event_code – The code of the event that triggered the data transmission.

template<typename ObjectType>
inline bool ExtractParameters(ObjectType &storage_object)

Unpacks the instance’s runtime parameters received from the PC into the specified storage object.

Template Parameters:

ObjectType – The type of the object used to store the PC-addressable module’s parameters.

Parameters:

storage_object – The object used to store the PC-addressable module’s parameters.

Returns:

@bool True if the parameters were successfully unpacked, false otherwise.

Protected Attributes

const uint8_t _module_type

Stores the instance’s type (family) identifier code.

const uint8_t _module_id

Stores the instance’s unique identifier code.

const uint16_t _module_type_id = _module_type << 8 | _module_id

Stores the instance’s combined type and id uint16 code expected to be unique for each module instance active at the same time.

Communication &_communication

The Communication instance used to send module runtime data to the PC.

Protected Static Functions

static inline uint16_t AnalogRead(const uint8_t pin, const uint16_t pool_size = 0)

Polls and (optionally) averages the value(s) of the specified analog pin.

Parameters:
  • pin – The analog pin to read.

  • pool_size – The number of pin readout values to average into the returned value. Set to 0 or 1 to disable averaging.

Returns:

uint16_t The read analog value.

static inline bool DigitalRead(const uint8_t pin, const uint16_t pool_size = 0)

Polls and (optionally) averages the value(s) of the specified digital pin.

Parameters:
  • pin – The digital pin to read.

  • pool_size – The number of pin readout values to average into the returned value. Set to 0 or 1 to disable averaging.

Returns:

bool The read digital value as true (HIGH) or false (LOW).

struct ExecutionControlParameters
#include <module.h>

This structure stores the data that supports executing module-addressed commands sent from the PC interface.

Warning

End users should not modify any elements of this structure directly. This structure is modified by the Kernel and certain utility methods inherited from the base Module class.

Public Members

uint8_t command = 0

Currently executed (in-progress) command.

uint8_t stage = 0

The stage of the currently executed command.

bool noblock = false

Determines whether the currently executed command is blocking.

uint8_t next_command = 0

Stores the next command to be executed.

bool next_noblock = false

Stores the noblock flag for the next command.

bool new_command = false

Tracks whether next_command is a new or recurrent command.

bool run_recurrently = false

Tracks whether next_command is recurrent (cyclic).

uint32_t recurrent_delay = 0

The delay, in microseconds, between command repetitions.

elapsedMicros recurrent_timer

Measures recurrent command activation delays.

elapsedMicros delay_timer

Measures delays between command stages.