owlparser_web_logo

OwlParser C++ library

v2.0.0

Table of contents

Overview

The OwlParser is a C++ library for encoding control commands and checking responses for Owl 640 and Owl 1280 cameras. The library uses a single unified OwlCommand enum. Commands that are common to both cameras (e.g. SET_SYSTEM_STATE, SET_EXPOSURE_CMD1) have no prefix and use a cameraType parameter (640 or 1280) to select the correct protocol encoding. Commands specific to one camera keep their prefix: OWL640_ for Owl 640-only commands (e.g. OWL640_SET_TRIGGER_OUTPUT, OWL640_SET_GAMMA) and OWL1280_ for Owl 1280-only commands (e.g. OWL1280_SET_TRIG_DELAY_CMD1, OWL1280_SET_TEST_PATTERN). It includes basic methods for preparing commands (encoding) and interpreting the camera responses (checking command arguments). It uses C++17 standard. The library provides simple interface and doesn’t have third party dependencies to be specially installed in OS. Also, the library provides an interactive test application to communicate with cameras via serial ports. The test application depends on SerialPort library (provides methods to work with serial ports, source code included, Apache 2.0 license).

Versions

Table 1 - Library versions.

Version Release date What’s new
1.0.0 04.05.2023 - First version.
1.0.1 27.03.2024 - Documentation added.
- Code optimized.
1.0.2 23.05.2024 - Documentation updated.
1.0.3 31.07.2024 - CMake structure updated.
1.0.4 26.11.2024 - Update included headers.
1.0.5 26.10.2025 - SerialPort submodule update for test application.
2.0.0 21.03.2026 - Added Owl 1280 camera support.
- Unified OwlCommand enum for both cameras.
- Interactive menu-driven test application.

Library files

The library is supplied only as source code. The user is given a set of files in the form of a CMake project (repository). The repository structure is shown below:

CMakeLists.txt ------------- Main CMake file of the library.
src  ----------------------- Folder with library source code.
    CMakeLists.txt --------- CMake file of the library.
    OwlParser.h ------------ Main library header file.
    OwlParserVersion.h ----- Header file with library version.
    OwlParserVersion.h.in -- File for CMake to generate version header.
    OwlParser.cpp ---------- C++ implementation file.
test ----------------------- Folder for test application files.
    3rdparty --------------- Folder with third-party libraries.
        CMakeLists.txt ----- CMake file to include third-party libraries.
        SerialPort --------- Folder with SerialPort library source code.
    CMakeLists.txt --------- CMake file for test application.
    main.cpp --------------- Source C++ file of test application.

OwlParser class description

Class declaration

class OwlParser
{
public:
    
    /// Get library version.
    static std::string getVersion();
    
    /// Encode command for OWL camera.
    bool encodeCommand(uint8_t *data,
                        int &size,
                        OwlCommand id,
                        int cameraType = 640,
                        uint32_t arg1 = 0,
                        uint32_t arg2 = 0,
                        uint32_t arg3 = 0,
                        uint32_t arg4 = 0);

    /// Process reply data for OWL camera.
    OwlReply processReply(OwlCommand commandId,
                            uint8_t commandCrc,
                            uint8_t nextByte,
                            std::vector<uint32_t> &params,
                            int cameraType = 640);

private:

    /// Buffer size.
    static const int m_bufferSize{32};
    /// Input data buffer.
    uint8_t m_inputBuffer[m_bufferSize]{};
};

getVersion method

The getVersion() method return string of current OwlParser class version. Method declaration:

static std::string getVersion();

Method can be used without OwlParser class instance:

std::cout << "OwlParser version: " << OwlParser::getVersion();

Console output:

OwlParser version: 2.0.0

encodeCommand method

The encodeCommand(…) method encodes (prepares data) control command for camera. A single method handles both Owl 640 and Owl 1280 commands through the unified OwlCommand enum. Shared commands (without prefix) use the cameraType parameter to select the correct protocol encoding. Camera-specific commands (prefixed with OWL640_ or OWL1280_) ignore the cameraType parameter. See Command encoding example for usage. Method declaration:

bool encodeCommand(uint8_t *data,
                    int &size,
                    OwlCommand id,
                    int cameraType = 640,
                    uint32_t arg1 = 0,
                    uint32_t arg2 = 0,
                    uint32_t arg3 = 0,
                    uint32_t arg4 = 0);
Parameter Value
data Address of buffer for encoded data (command). Size of buffer also depends on command id but it is better to give at least 10 bytes.
size Size of encoded command.
id Command ID according to OwlCommand enum.
cameraType Camera type: 640 or 1280. Used by shared commands to select the correct protocol encoding. Default: 640.
arg1-arg4 Arguments of command. The value of arguments depends on command ID.

Returns: TRUE if commands encoded or FALSE if not (invalid ID or invalid parameters).

processReply method

The processReply(…) method processes the camera response. A single method handles both Owl 640 and Owl 1280 commands through the unified OwlCommand enum. The cameraType parameter determines how the reply data is parsed, since Owl 640 and Owl 1280 cameras use different reply formats for the same commands. See the Response processing example. Once the data from the serial port has been read the user must pass it to the method byte-by-byte (each byte separately in sequence). The library has an internal ring buffer. When the user passes another byte to the method, the library shifts the ring buffer by one byte and copies the new byte to the end of the buffer. If the library detects a valid response in the ring buffer, it returns the response ID (see OwlReply enum) and returns the response arguments. Method declaration:

OwlReply processReply(OwlCommand commandId,
                        uint8_t commandCrc,
                        uint8_t nextByte,
                        std::vector<uint32_t> &params,
                        int cameraType = 640);
Parameter Value
commandId Command ID according to OwlCommand enum.
commandCrc CRC of command.
nextByte Next byte of response.
params Vector of parameters. Number of parameters depends on command.
cameraType Camera type: 640 or 1280. Determines how reply data is parsed. Default: 640.

Returns: OwlReply enum value.

Important: The library detects camera replies by matching the last received byte against the command checksum (commandCrc). This means the camera must have checksum mode enabled — the camera will then append the command CRC to every response. Checksum mode is controlled by the arg1 parameter of the SET_SYSTEM_STATE command. Set arg1 = 1 to enable checksums. If checksum mode is disabled (arg1 = 0), the camera will not append a CRC byte to its replies, and the processReply method will be unable to detect any response (it will always return NO_MESSAGE).

Data structures

OwlCommand enum

The command IDs are described in the OwlCommand enum in the OwlParser.h file. All commands for both Owl 640 and Owl 1280 cameras are combined into this single enum. Commands prefixed with OWL640_ are for the Owl 640 camera, and commands prefixed with OWL1280_ are for the Owl 1280 camera. Some commands that are logically the same for both cameras (e.g. SET_SYSTEM_STATE, RESET) have separate entries for each camera type. Many protocol operations require multiple sub-commands (e.g. CMD1, CMD2, CMD3, CMD4) to set or get a single value — all sub-commands in a group take the same arguments. The definition of the enum is as follows:

enum class OwlCommand
{
    // ---- Shared commands (both OWL 640 and OWL 1280) ----
    // Use cameraType parameter (640 or 1280) to select protocol encoding.

    /// Set system state. arg1: Checksum 0=off/1=on. arg2: ACK 0=off/1=on.
    /// OWL640: arg3: FPGA 0=stop/1=run. arg4: EEPROM 0=off/1=on.
    /// OWL1280: arg3: FPGA 0=hold reset/1=normal.
    SET_SYSTEM_STATE,
    /// Micro reset. Traps Micro causing watchdog reset.
    MICRO_RESET,
    /// Set camera control register 0.
    /// arg1: VertFlip 0=off/1=on. arg2: HorFlip 0=off/1=on.
    /// arg3: ALC 0=off/1=on. arg4: TEC 0=off/1=on.
    SET_CAMERA_CONTROL_REGISTER_0,
    /// Set camera control register 1.
    /// OWL640: arg1: AGMC 0=off/1=on. arg2: Fan 0=off/1=on.
    /// OWL1280: arg1: SDI Sync 0=off/1=on.
    SET_CAMERA_CONTROL_REGISTER_1,
    /// Set exposure. 4 sub-commands for 32-bit value.
    /// OWL640: 1 unit = 25 ns. OWL1280 low gain: 1 unit = 1 usec.
    /// OWL1280 high gain: 1 unit = 10 usec.
    SET_EXPOSURE_CMD1 .. SET_EXPOSURE_CMD4,
    /// Set digital video gain. 2 sub-commands. arg1: gain*256.
    SET_DIGITAL_VIDEO_GAIN_CMD1, SET_DIGITAL_VIDEO_GAIN_CMD2,
    /// Set gain/trigger mode. arg1: 0=int/1=ext trigger.
    /// arg2: 0=-ve/1=+ve edge. arg3: gain mode. arg4 (640 only): gain.
    SET_GAIN_TRIGGER_MODE,
    /// Set frame rate. 4 sub-commands for 32-bit value.
    /// OWL640: 1 count = 25 ns. OWL1280: 1 count = 14.2857 ns.
    SET_FRAME_RATE_CMD1 .. SET_FRAME_RATE_CMD4,
    /// Set TEC set point. 2 sub-commands. arg1: 12-bit DAC value.
    SET_TEC_SET_POINT_CMD1, SET_TEC_SET_POINT_CMD2,
    /// Set NUC state. arg1: NUC mode (0-4). arg2: Bad Pixels 0=off/1=on.
    SET_NUC_STATE,
    /// Set ALC level. 2 sub-commands. arg1: 14-bit value (max 0x3FFF).
    SET_ALC_LEVEL_CMD1, SET_ALC_LEVEL_CMD2,
    /// Set peak/average. arg1: 0=full peak, 255=full average.
    SET_PEAK_AVERAGE,
    /// Set ROI appearance. arg1: ROI mode.
    SET_ROI_APPEARANCE,
    /// Set ROI X/Y offset and size. arg1: 8-bit value.
    SET_ROI_X_OFFSET, SET_ROI_Y_OFFSET,
    SET_ROI_X_SIZE, SET_ROI_Y_SIZE,
    /// Get system status. 2 sub-commands.
    GET_SYSTEM_STATUS,
    /// Get camera control register 0. 2 sub-commands.
    GET_CAMERA_CONTROL_REGISTER_0_CMD1, GET_CAMERA_CONTROL_REGISTER_0_CMD2,
    /// Get camera control register 1. 2 sub-commands.
    GET_CAMERA_CONTROL_REGISTER_1_CMD1, GET_CAMERA_CONTROL_REGISTER_1_CMD2,
    /// Get gain/trigger mode. 2 sub-commands.
    GET_GAIN_TRIGGER_MODE_CMD1, GET_GAIN_TRIGGER_MODE_CMD2,
    /// Get frame rate. 8 sub-commands.
    GET_FRAME_RATE_CMD1 .. GET_FRAME_RATE_CMD8,
    /// Get TEC set point. 4 sub-commands.
    GET_TEC_SET_POINT_CMD1 .. GET_TEC_SET_POINT_CMD4,
    /// Get NUC state. 2 sub-commands.
    GET_NUC_STATE_CMD1, GET_NUC_STATE_CMD2,
    /// Get exposure value. 8 sub-commands.
    GET_EXPOSURE_VALUE_CMD1 .. GET_EXPOSURE_VALUE_CMD8,
    /// Get digital gain. 4 sub-commands.
    GET_DIGITAL_GAIN_CMD1 .. GET_DIGITAL_GAIN_CMD4,
    /// Get auto level. 4 sub-commands.
    GET_AUTO_LEVEL_CMD1 .. GET_AUTO_LEVEL_CMD4,
    /// Get peak/average setting. 2 sub-commands.
    GET_PEAK_AVERAGE_SETTING_CMD1, GET_PEAK_AVERAGE_SETTING_CMD2,
    /// Get AGC speed. 2 sub-commands.
    GET_AGC_SPEED_CMD1, GET_AGC_SPEED_CMD2,
    /// Get ROI appearance. 2 sub-commands.
    GET_ROI_APPEARANCE_CMD1, GET_ROI_APPEARANCE_CMD2,
    /// Get ROI X/Y offset. 2 sub-commands each.
    GET_ROI_X_OFFSET_CMD1, GET_ROI_X_OFFSET_CMD2,
    GET_ROI_Y_OFFSET_CMD1, GET_ROI_Y_OFFSET_CMD2,
    /// Get ROI X/Y size. 2 sub-commands each.
    GET_ROI_X_SIZE_CMD1, GET_ROI_X_SIZE_CMD2,
    GET_ROI_Y_SIZE_CMD1, GET_ROI_Y_SIZE_CMD2,
    /// Get video peak value. 4 sub-commands.
    GET_VIDEO_PEAK_VALUE_CMD1 .. GET_VIDEO_PEAK_VALUE_CMD4,
    /// Get video average value. 4 sub-commands.
    GET_VIDEO_AVERAGE_VALUE_CMD1 .. GET_VIDEO_AVERAGE_VALUE_CMD4,
    /// Get sensor PCB temperature. 4 sub-commands.
    GET_SENSOR_PCB_TEMPERATURE_CMD1 .. GET_SENSOR_PCB_TEMPERATURE_CMD4,
    /// Get sensor temperature. 4 sub-commands.
    GET_SENSOR_TEMPERATURE_CMD1 .. GET_SENSOR_TEMPERATURE_CMD4,
    /// Get micro version.
    GET_MICRO_VERSION,
    /// Get master FPGA version. 4 sub-commands.
    GET_MASTER_FPGA_VERSION_CMD1 .. GET_MASTER_FPGA_VERSION_CMD4,
    /// Get slave FPGA version. 4 sub-commands.
    GET_SLAVE_FPGA_VERSION_CMD1 .. GET_SLAVE_FPGA_VERSION_CMD4,
    /// Get unit serial number. 2 sub-commands.
    GET_UNIT_SERIAL_NUMBER_CMD1, GET_UNIT_SERIAL_NUMBER_CMD2,
    /// Get manufacturer data. 2 sub-commands.
    GET_MANUFACTURER_DATA_CMD1, GET_MANUFACTURER_DATA_CMD2,

    // ---- OWL 640-only commands ----

    /// Set AGC speed (640). arg1: Gain 0-15. arg2: Speed 0-15.
    OWL640_SET_AGC_SPEED,
    /// Set trigger output (640). arg1: 0=disable, 1=enable.
    OWL640_SET_TRIGGER_OUTPUT,
    /// Set Gamma (640). arg1: 0=disable, 1=enable.
    OWL640_SET_GAMMA,
    /// Get Gamma (640). 2 sub-commands.
    OWL640_GET_GAMMA_CMD1, OWL640_GET_GAMMA_CMD2,

    // ---- OWL 1280-only commands ----

    /// Set ALC speed (1280). arg1: Gain 0-15. arg2: Speed 0-15.
    OWL1280_SET_ALC_SPEED,
    /// Set trig delay (1280). 4 sub-commands. 1 count = 14.2857 ns.
    OWL1280_SET_TRIG_DELAY_CMD1 .. OWL1280_SET_TRIG_DELAY_CMD4,
    /// Set test pattern (1280). arg1: pattern mode (1-6).
    OWL1280_SET_TEST_PATTERN,
    /// Set SDI output (1280). arg1: 0=internal, 1=external trigger.
    OWL1280_SET_SDI_OUTPUT,
    /// Get trig delay (1280). 4 sub-commands.
    OWL1280_GET_TRIG_DELAY_CMD1 .. OWL1280_GET_TRIG_DELAY_CMD4,
    /// Get test pattern (1280).
    OWL1280_GET_TEST_PATTERN,
    /// Get SDI output (1280).
    OWL1280_GET_SDI_OUTPUT
};

The OwlCommand enum contains all possible commands for both Owl 640 and Owl 1280 cameras. Shared commands have no prefix and use the cameraType parameter to select the correct protocol encoding. Camera-specific commands use OWL640_ or OWL1280_ prefix. Each command has its own set of arguments. The user must set arguments according to the command description (see OwlParser.h for detailed parameter descriptions). For commands where the protocol requires multiple sub-commands (e.g. CMD1..CMD4), all sub-commands in a group take the same arguments.

OwlReply enum

The OwlReply enum contains all possible responses from the camera. The definition of the structure is as follows:

enum class OwlReply
{
    /**
     * @brief No message.
     */
    NO_MESSAGE,
    /**
     * @brief Command acknowledge - command processed successfully.
     */
    ETX,
    /**
     * @brief Partial command packet received, camera timed out waiting for end
     * of packet. Command not processed.
     */
    ETX_SER_TIMEOUT,
    /**
     * @brief Check sum transmitted by host did not match that calculated for the
     * packet. Command not processed.
     */
    ETX_CK_SUM_ERR,
    /**
     * @brief An I2C command has been received from the Host but failed
     * internally in the camera.
     */
    ETX_I2C_ERR,
    /**
     * @brief Data was detected on serial line, command not recognized.
     */
    ETX_UNKNOWN_CMD,
    /**
     * @brief Host Command to access the camera EEPROM successfully
     * received by camera but not processed as EEPROM is busy. I.e.
     * FPGA trying to boot.
     */
    ETX_DONE_LOW,
    /**
     * @brief Data.
     */
    DATA,
    /**
     * @brief Format error.
     */
    DATA_ERROR
};

Build and connect to your project

Typical commands to build OwlParser library:

cd OwlParser
mkdir build
cd build
cmake ..
make

If you want to connect OwlParser library to your CMake project as source code you can make follow. For example, if your repository has structure:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp

Create folder 3rdparty and copy folder of OwlParser repository there. New structure of your repository:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp
3rdparty
    OwlParser

Create CMakeLists.txt file in 3rdparty folder. CMakeLists.txt should contain:

cmake_minimum_required(VERSION 3.13)

################################################################################
## 3RD-PARTY
## dependencies for the project
################################################################################
project(3rdparty LANGUAGES CXX)

################################################################################
## SETTINGS
## basic 3rd-party settings before use
################################################################################
# To inherit the top-level architecture when the project is used as a submodule.
SET(PARENT ${PARENT}_YOUR_PROJECT_3RDPARTY)
# Disable self-overwriting of parameters inside included subdirectories.
SET(${PARENT}_SUBMODULE_CACHE_OVERWRITE OFF CACHE BOOL "" FORCE)

################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
if (${PARENT}_SUBMODULE_OWL_PARSER)
    add_subdirectory(OwlParser)
endif()

File 3rdparty/CMakeLists.txt adds folder OwlParser to your project and excludes test application and example from compiling (by default test applications and example are excluded from compiling if OwlParser is included as sub-repository). The new structure of your repository:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp
3rdparty
    CMakeLists.txt
    OwlParser

Next you need include folder 3rdparty in main CMakeLists.txt file of your repository. Add string at the end of your main CMakeLists.txt:

add_subdirectory(3rdparty)

Next you have to include Lens library in your src/CMakeLists.txt file:

target_link_libraries(${PROJECT_NAME} OwlParser)

Done!

Examples

Command encoding example

Below is an example of encoding a command for Owl 640 camera. The cameraType parameter (4th argument) selects the protocol encoding. Note that the first argument after cameraType enables checksum mode (arg1 = 1), which is required for the processReply method to detect camera responses (see processReply method).

// Init variables.
const int bufferSize = 1024; // Enough buffer size.
uint8_t buffer[bufferSize];
cr::owl::OwlParser parser;
int bytes = 0;

// Encode command for Owl 640 (cameraType = 640).
// arg1=1 enables checksum in camera replies.
if (!parser.encodeCommand(buffer, bytes,
        cr::owl::OwlCommand::SET_SYSTEM_STATE, 640, 1, 1, 1, 0))
{
    std::cout << "Command not encoded" << std::endl;
    return;
}

// Clear serial port buffer.
g_serialPort.read(buffer, bufferSize);

// Send command.
if (g_serialPort.write(buffer, bytes) != bytes)
{
    std::cout << "Data not sent" << std::endl;
    return;
}

Below is an example of encoding the same command for Owl 1280 camera (same method and enum, different cameraType).

// Encode command for Owl 1280 (cameraType = 1280).
if (!parser.encodeCommand(buffer, bytes,
        cr::owl::OwlCommand::SET_SYSTEM_STATE, 1280, 1, 1, 1, 0))
{
    std::cout << "Command not encoded" << std::endl;
    return;
}

Response processing example

Below is an example of processing response.

// Init variables.
std::vector<uint32_t> params;
uint8_t commandCrc = 0;
cr::owl::OwlCommand commandId = cr::owl::OwlCommand::SET_SYSTEM_STATE;
int cameraType = 640; // or 1280
// Buffer for received data.
uint8_t buffer[1024];

// Read data from serial port.
int bytesRead = g_serialPort.read(buffer, 1024);

// Process response.
for (int i = 0; i < bytesRead; i++)
{
    cr::owl::OwlReply reply = parser.processReply(
            commandId, commandCrc, buffer[i], params, cameraType);

    // Use response ...
    if (reply == cr::owl::OwlReply::ETX)
    {
        std::cout << "Command processed successfully" << std::endl;
        for (int j = 0; j < params.size(); j++)
        {
            std::cout << "Param " << j << ": " << params[j] << std::endl;
        }
    }
    else if (reply == cr::owl::OwlReply::ETX_SER_TIMEOUT)
    {
        std::cout << "Timeout" << std::endl;
    }
    else if (reply == cr::owl::OwlReply::ETX_CK_SUM_ERR)
    {
        std::cout << "Checksum error" << std::endl;
    }
    else if (reply == cr::owl::OwlReply::ETX_I2C_ERR)
    {
        std::cout << "I2C error" << std::endl;
    }
    else if (reply == cr::owl::OwlReply::ETX_UNKNOWN_CMD)
    {
        std::cout << "Unknown command" << std::endl;
    }
    else if (reply == cr::owl::OwlReply::ETX_DONE_LOW)
    {
        std::cout << "EEPROM busy" << std::endl;
    }
}

Test application

Folder OwlParser/test contains the interactive test application. On startup, the application prompts the user to enter the serial port name (e.g. /dev/ttyUSB0) and the camera type (640 or 1280). The serial port is opened at the default baudrate of 115200 (RS485, 8N1) with a response timeout of 500 msec.

Important: Before sending other commands, the user should first send the SET System State command with Checksum = 1 (enabled). The library’s reply detection relies on the camera appending a checksum byte to every response. If checksum mode is not enabled, the library will return NO_MESSAGE for all camera replies even though the camera did respond.

After connecting, the application displays a numbered menu of all available commands for the selected camera type. The user selects a command by number. For SET commands, the application prompts for the required parameters with descriptive hints (e.g. Counts (1 count = 25 ns (40MHz)): ). For GET commands no parameters are needed. The application then encodes the command, sends it to the camera, receives the reply, decodes it, and prints the result.

Commands that require multiple protocol sub-commands (e.g. SET Exposure which needs CMD1, CMD2, CMD3, CMD4) are grouped into a single menu entry. The user enters the parameter values only once, and the application automatically sends all sub-commands with the same arguments. This applies to both SET and GET multi-command groups.

For each sub-command the application prints:

  • TX: the raw bytes sent to the camera.
  • RX: the raw bytes received with response time in milliseconds.
  • Result: the decoded reply type (ETX/ACK, DATA with parameters, or error).

Enter 0 to exit the application.

Example session output:

#########################################
OwlParser v2.0.0 interactive test.
#########################################

Enter serial port name (e.g. /dev/ttyUSB0): /dev/ttyUSB0
Enter camera type (640 or 1280, default 640): 640
Serial port /dev/ttyUSB0 open at 115200 baud. Camera: OWL 640

========================================
 Available commands:
========================================
  1. SET System State
  2. RESET
  3. SET Camera Control Register 0
  ...
  20. GET System Status
  ...
  41. GET Gamma
  0. Exit
========================================
Select command (0 to exit): 5

>>> SET Exposure
  Counts (1 count = 25 ns (40MHz)): 40000
  --- sub-command 1/4 ---
  TX: 53 e0 2 44 9c 0 50 2b
  RX (12 ms): 6 3
  Result: ETX (ACK)
  --- sub-command 2/4 ---
  TX: 53 e0 2 45 9c 0 50 2a
  RX (11 ms): 6 3
  Result: ETX (ACK)
  --- sub-command 3/4 ---
  ...
  --- sub-command 4/4 ---
  ...
  OK

Table of contents