This page describes the contents of the OpenLCB OlcbCommonCAN C/C++ library. This library is part of the prototype, proof-of-concept software implementing the OpenLCB protocols on several platforms, including standalone PCs and Arduinos.
It is a CAN-specific complete implementation for simple leaf nodes.This library provides the basic implementation classes.
It is structured as "Objects that handle one particular state machine or group of interactions".
Basic implemented types include:
NodeID is a "struct with methods" to handle the bytes of an NodeID. It's more of a data object than a state machine handler, but has some convenient service methods.
EventID is a "struct with methods" to handle the bytes of an EventID. It's more of a data object than a state machine handler, but has some convenient service methods.
Event - Used for local information about a specific event. This is an EventID, plus some local state information used by the PCE object to handle state transitions.
Key objects with links to more information (others in a section below), in increasing height within the protocol stack:
LinkControl handles the state machine for starting up the link, assigning an alias, sending the Initialization Complete, watching for an interfering node, etc. The program needs to feed frames to this (see runtime section below), and should check for link initialized before doing anything else on the OpenLCB network.
PCE handles the Producer/Consumer registration, replying to requests for Producer and Consumer identification, etc, and makes it easy to produce and consume events. The using code provides arrays of Events that are consumed or can be produced. Once the link is up, the using code can then tell the PCE to produce an event, and gets a callback when it can consume an event from the link.
Datagram handles receipt and sending of Datagrams.
OlcbStream handles the receipt and sending of Stream information. (The name was changed from "Stream" to avoid a collision with Std C++ names.)
NodeMemory handles saving and restoring node state (NodeID, EventIDs) to persistent memory.
Configuration handles the remote configuration protocol.
BG handles the Blue/Gold configuration management through buttons and LEDs.
ButtonProtocol handles remote access to buttons and LEDs.
PIP handles the Protocol Identification Protocol.
SNII handles the Simple Node Identification Information protocol.
This section describes the basic structure of these proof-of-concept implementations.
We want this code to be general, so people building any type of hardware can easily and rapidly adapt it to run on their hardware.
On the other hand, we're developing on a specific hardware platform, using a specific interface (the MicroChip MP2515) and library (can.h from Fabian Greif, Roboterclub Aachen e.V., adapted and extended by Alex Shepherd)
To this end, we provide an abstraction layer for the hardware that localizes all CAN access to a small number of C calls and data structures. This is implemented via the OpenLcbCanInterface.h and .cpp files. (It's in C++, but it's not implemented as a class now, just a bunch of methods; the data structures are provided as arguments to calls)
This code has to run using the Arduino CAN library, which is not threaded and has manually-managed buffers.
A transmit buffer may not be available when the code wants to send a message. It's possible to sit and spin-loop, waiting for a buffer to become available, as on a low-traffic link that will generally take less than (29+8*8+16+25)/125000, about a millisecond. But that won't work well if the line is very busy, e.g. during startup, or there are transmission problems, e.g. if the node is not properly connected.
Therefore, the code is structured around a state machine. Incoming messages or other conditions that result in the need to send a message result in state transitions in the code, and can send a message immediately if a buffer is available. If not, the state is checked during routine processing later on, and results in sending the message then.
There are a couple ways to structure code like this. Often, high level classes encapsulate and use references to lower level objects, resulting in a classic “stack” form. For OpenLCB, this would result in (insert diagram here) e.g. a PCE object that's passed a LinkControl object through its constructor, and does all I/O through that. In turn the LinkControl object is passed a OpenLcbCanInterface object via it's constructor, and uses that for all I/O. Finally, the OpenLcbInterface provides all the state and code to handle all the interactions, and is initialized via a constructor. Frames received via CAN are passed up throught eh stack as appropriate. Once a standard is in place, this is a very powerful structure which results in well-encapsulated software. However, during development, it produces a structure that requires work at many levels at once.
During the development phase, we're using a different structure. The objects exist, but control of upward message flow and overall state is done outside the “stack”. The sketch's loop() routine has to check for an incoming frame, then pass it to objects depending on state.
The using code has to provide (a pair of?) buffers, and an initialized NodeID with the proper value....
In the sketch setup() routine, the using code needs to:
initialise the CAN interface
initialize the LinkControl object
initialize any PCE objects used
in additional any initialization of its own.
In the sketch loop() routine, the using code needs to:
pass received frames to the LinkControl
periodically invoke LinkControl
Optionally …
We'll restructure this into the more powerful form at a later step of development.
This section is a brief description of each file, class or library.
Basic definitions of constants.
OpenLcbCanBuffer wraps a transmit or receive CAN buffer to add creation and identification methods. This approach uses a bit more code space than writing ands/ors for each decode, but makes much more readable application code.
OpenLcbCanInterface wraps the external hardware for the CAN interface. See the interface section above.
This web sites contains trademarks and copyrighted information. Please see the Licensing page.
This is SVN $Revision: 2685 $ of