OpenLCB C/C++ Library: OlcbCommonCAN

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.

Introduction

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:

Key objects with links to more information (others in a section below), in increasing height within the protocol stack:

Structure

This section describes the basic structure of these proof-of-concept implementations.

CAN Interface

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)

Threading

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.

Dependency Design

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.

Setup

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:

in additional any initialization of its own.

Runtime

In the sketch loop() routine, the using code needs to:

Optionally …

We'll restructure this into the more powerful form at a later step of development.

Classes/Files/Libraries

This section is a brief description of each file, class or library.

OpenLCB

Basic definitions of constants.

OpenLcbCanBuffer

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

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 08/16/09.