Table of Contents

Binary Protocol 8-bit (harp-1.0)

Introduction

The Harp Protocol is a binary communication protocol created in order to facilitate and unify the interaction between different devices. It was designed with efficiency and ease of parsing in mind.

The protocol is based on addresses. Each address points to a certain memory position available in the device. These positions are called registers. Each register is defined by a data type and some meaningful functionality attached to the data.

The Harp Binary Protocol is commonly used for all exchanges between a Controller and a Device. The controller can be a computer, or a server and the device can be a data acquisition or actuator microcontroller.

The available packets are:

  • Command: Sent by the Controller to the Device. Command messages can be used to read or write the register contents.
  • Reply: Sent by the Device in response to a Command.
  • Event: Sent by the Device when an external or internal event of interest happens. An Event message will always carry the contents of the register that the event refers to.

Note

The Harp Binary Protocol uses Little-Endian byte ordering.

Harp Message specification

The Harp Message contains a minimal amount of information to execute a well-defined exchange of data. It follows the structure below.

Harp Message
MessageType
Length
Address
Port
PayloadType
Payload
Checksum

MessageType (1 byte)

Specifies the type of the Harp Message.

Value Description
1 (Read) Read the content of the register with address [RegisterAddress]
2 (Write) Write the content to the register with address [RegisterAddress]
3 (Event) Send the content of the register with address [RegisterAddress]

Length (1 byte)

Contains the number of bytes that are still available and need to be read to complete the Harp message (i.e. number of bytes after the field [Length]).

Address (1 byte)

Contains the address of the register to which the Harp Message refers to.

Port (1 byte)

If the device is a Hub of Harp Devices, it indicates the origin or destination of the Harp Message. If the field is not used or it’s equal to 0xFF, it points to the device itself.

PayloadType (1 byte)

Indicates the type of data available on the [Payload]. The structure of this byte follows the following specification:

7 6 5 4 3 2 1 0
IsSigned IsFloat 0 HasTimestamp Type

Type (4 bits)

Specifies the size of the word in the [Payload].

Value Description
1 8 bits
2 16 bits
4 32 bits
8 64 bits

HasTimestamp (1 bit)

If this bit is set the Harp Message contains a timestamp. In this case the fields [Seconds] and [Microseconds] must be present in the message.

IsFloat (1 bit)

This bit indicates whether the [Payload] represents fractional values. If the bit is not set, the payload contains integers.

IsSigned (1 bit)

If the bit is set, indicates that the [Payload] contains integers with signal.

Note

The bits [IsFloat] and [IsSigned] must never be set simultaneously.

Payload (? bytes)

The content of the Harp Message.

If the [HasTimestamp] flag is set, the following optional fields are present at the beginning of the message payload:

Seconds (4 bytes)

Contains the number of seconds (U32) of the Harp Timestamp clock. This field is optional. In order to indicate that this field is available, the bit [HasTimestamp] in the field [PayloadType] needs to be set.

Microseconds (2 bytes)

It contains the fractional part of the Harp Timestamp clock in microseconds (U16 containing the number of microseconds divided by 32).

This field is optional. In order to indicate that this field is available, the bit [HasTimestamp] in the field [PayloadType] needs to be set.

Note

The full timestamp information can thus be retrieved using the formula: Timestamp(s) = [Seconds] + [Microseconds] * 32 * 10-6

Checksum (1 byte)

The sum of all bytes (U8) contained in the Harp Message. The receiver of the message should calculate the checksum and compare it with the received. If they don’t match, the Harp Message should be discarded.


Features and Code Examples

Some of the fields described on the previous chapter have special features. These are presented next.

MessageType and ErrorFlag

The field [Command] has an Error flag on the 4th least significant bit. When this bit is set it means that an error has occured. Examples of possible errors cane be:

  1. The controller tries to read from a register that doesn’t exist;
  2. The controller tries to write invalid data to a certain register;
  3. The [PayloadType] doesn’t match the target register specification.

A simple code in C to check for error will be:

    int errorMask = 0x08;

    if (Command & errorMask)
    {
    printf(“Error detected.\n”);
    }

Harp Message Length

If one byte is not enough to express the length of the Harp Message, use [Length] equal to 255 and add after an unsigned 16 bits word with the Harp Message length.

Replace the [Length] with: [255] (1 byte) [ExtendedLength] (2 bytes)

Parsing PayloadType

For the definition of the PayloadType types, a C# code snippet is presented.

Note that the time information can appear without an element Timestamp<>.

  int isUnsigned = 0x00;
  int isSigned = 0x80;
  int isFloat = 0x40;
  int hasTimestamp = 0x10;

  enum PayloadType 
  {
      U8  = (isUnsigned | 1),
      S8  = (isSigned   | 1),
      U16 = (isUnsigned | 2),
      S16 = (isSigned   | 2),
      U32 = (isUnsigned | 4),
      S32 = (isSigned   | 4),
      U64 = (isUnsigned | 8),
      S64 = (isSigned   | 8),
      Float = (isFloat  | 4),
      Timestamp = hasTimestamp,
      TimestampedU8  = (hasTimestamp | U8),
      TimestampedS8  = (hasTimestamp | S8),
      TimestampedU16 = (hasTimestamp | U16),
      TimestampedS16 = (hasTimestamp | S16),
      TimestampedU32 = (hasTimestamp | U32),
      TimestampedS32 = (hasTimestamp | S32),
      TimestampedU64 = (hasTimestamp | U64),
      TimestampedS64 = (hasTimestamp | S64),
      TimestampedFloat = (hasTimestamp | Float)
  }

The field PayloadType has a flag on the 5th least significant bit that indicates if the time information is available on the Harp Message. The existence of this flag is useful to know if the fields [Seconds] and [Microseconds] are present on the Harp Message. In C one can check if the time information is avaible by using the following snippet:

int hasTimestamp = 0x10;

if (PayloadType &  hasTimestamp )
{
    printf(“The time information is available on the Harp Message’s Payload.\n”);
}

Using Checksum to validate communication integrity

The [Checksum] field is the sum of all bytes contained in the Harp Message. The receiver of the message should calculate the checksum and compare it with the received. If they don’t match, the Harp Message should be discarded. Example on how to calculate the [Checksum] in C language:

unsigned char Checksum = 0;
int i = 0;
for (; i < Length + 1; i++ )
{
    Checksum += HarpMessage(i);
}

Parsing [Payload] with Arrays

The [Payload] element can contain a single, or an array of values of the same type. The first step to parse these payloads is to first find the number of values contained on the [Payload] element. This can be done using the following C code example:

int arrayLength;
int hasTimestamp = 0x10;
int sizeMask = 0x0F;

if (PayloadType & hasTimestamp)
{
    // Harp Message has time information
    arrayLength = (Length – 10) / (PayloadType & sizeMask )
}
else
{
    // Harp Message doesn’t have time information
    arrayLength = (Length – 4) / (PayloadType & sizeMask )
}

Typical usage

Commands

The device that implements this Harp Protocol receives Write and Read commands from the controller, and replies with a copy of the message, timestamped with the hardware time at which the command was applied.

Some Harp Messages are shown below to demonstrate the typical usage of the protocol between a device and a controller. Note that timestamp information is usually omitted in messages sent from the controller to the device, since actions are expected to run as soon as possible.

We will use the following abbreviations:

  • [CMD] is a Command (From the Controller to the Device);
  • [RPL] is a Reply (From Device to the Controller)
  • [EVT] is an Event. (A message sent from the Device to the Controller without a command (i.e. request) from the Controller)

Write Message

  • [CMD] Controller: 2 Length Address Port PayloadType T Checksum
  • [RPL] Device: 2 Length Address Port PayloadType Timestamp<T> Checksum OK
  • [RPL] Device: 10 Length Address Port PayloadType Timestamp<T> Checksum ERROR

The timestamp information in the [RPL] represents the time when the register with [Address] was updated.

Read Message

  • [CMD] Controller: 1 4 Address Port PayloadType Checksum
  • [RPL] Device: 1 Length Address Port PayloadType Timestamp<T> Checksum OK
  • [RPL] Device: 9 10 Address Port PayloadType Timestamp<T> Checksum ERROR

The timestamp information in the [RPL] represents the time when the register with [Address] was read.

Event message

  • [EVT] Device: 3 Length Address Port PayloadType Timestamp<T> Checksum OK

The timestamp information in [EVT] represents the time when the register with [Address] was read.


Release notes:

  • v0.1

    • First draft.
  • v0.2

    • Changed Event Command to 3.
  • v0.3

    • Cleaned up document and added C code examples.
    • First release.
  • v1.0

    • Updating naming of the protocol fields, etc, to latest naming review.
    • Major release.
  • v1.1

    • Corrected [PayloadType] list on page 2.
  • v1.2

    • Changed device naming to Controller and Peripheral.
  • v1.3

    • Minor corrections.
  • v1.4.0

    • Refactor documentation to markdown format.
    • Minor typo corrections.
    • Improve clarity of some sections.
    • Adopt semantic versioning.
  • v1.4.1

    • Remove table of contents to avoid redundancy with doc generators.
    • Avoid using verbatim literals in titles.
    • Change device naming to Controller and Device.