libtinylor
Single-file header library for controlling Light-O-Rama hardware
Loading...
Searching...
No Matches
tinylor.h File Reference

A tiny library for generating LOR protocol requests. More...

#include <stddef.h>
#include <stdint.h>
Include dependency graph for tinylor.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  lor_channel_set
 Represents a grouping of 16 channels, as a bit set, aligned to a 16-channel boundary (via a multiplier). More...
 
union  lor_effect_data
 Union of effect argument structures that may be required by assorted effect types: LOR_SET_LIGHTS, LOR_FADE, LOR_PULSE, and LOR_SET_DMX_INTENSITY. More...
 
struct  lor_unit_set
 Represents a set of unit IDs as a 256-bit bitset, used to address a request to an arbitrary subset of units in a single frame (see lor_set_units). Initialize with lor_unit_set_clear or by zero initialization before adding units. More...
 
struct  lor_req
 Represents a request to apply an effect to a set of channels on a specific unit. The effect may require additional arguments, which are stored in the args field. Fields may be set directly, or better yet, by using the provided helper functions which handle potential data validation/conversion that you may not want to do. More...
 

Macros

#define LOR_HEARTBEAT_BYTES   ((uint8_t[]) {0, 0xFF, 0x81, 0x56, 0})
 The pre-defined binary representation of a LOR heartbeat message.
 
#define LOR_HEARTBEAT_SIZE   5
 The length of the LOR heartbeat message LOR_HEARTBEAT_BYTES.
 
#define LOR_HEARTBEAT_DELAY_MS   500
 The intended delay in milliseconds between sending LOR heartbeats.
 
#define LOR_HEARTBEAT_DELAY_NS   500000000
 The intended delay in nanoseconds between sending LOR heartbeats.
 
#define LOR_UNIT_ID_ALL   0xFF
 The broadcast unit ID. A request addressed to this value is executed by every unit on the bus.
 
#define LOR_UNIT_ID_HOST   0xFE
 The reply marker. Frames sent from a unit back to the host (e.g. the response to a version query) begin with this value in place of a unit ID. It is never a valid destination for a request.
 
#define LOR_UNIT_ID_LIST   0xF2
 The unit list address. It is followed on the wire by a count byte and that many unit IDs; every unit whose ID appears in the list executes the request. Set automatically by lor_set_units.
 

Typedefs

typedef uint16_t lor_channel
 Represents a 0-based channel index, which is a unique identifier for a specific light or group of lights on a unit. Index 0 is the first channel (shown as channel 1 in LOR software), index 15 is the 16th. Valid indices are [0, 1023]. Indices 16 and above address additional 16-channel banks via the multipart channel format, which 16-channel controllers (e.g. CTB16PCg3) do not implement and silently discard.
 
typedef uint8_t lor_intensity
 Represents a scaled intensity value used by the LOR protocol.
 
typedef uint8_t lor_unit
 Represents a unit ID, which is a unique identifier for a piece of LOR hardware. Valid unit IDs are [1, 0xF0] (1-240); several units may share an ID, in which case they all execute the request. Reserved values: 0xFF (LOR_UNIT_ID_ALL) broadcasts to every unit, 0xF2 (LOR_UNIT_ID_LIST) introduces a unit list (see lor_set_units), and 0xFE (LOR_UNIT_ID_HOST) marks replies sent from a unit to the host. 0x00 is the frame delimiter and must never be used. 0xF1 and 0xF3-0xFD are unassigned; the CTB16PCg3 drops frames sent to them.
 
typedef uint16_t lor_decisec
 Represents a duration in deciseconds, which is 1/10th of a second.
 
typedef struct lor_channel_set lor_channel_set
 
typedef enum lor_effect lor_effect
 
typedef enum lor_channel_format lor_channel_format
 
typedef union lor_effect_data lor_effect_args_u
 
typedef struct lor_unit_set lor_unit_set
 
typedef struct lor_req lor_req_s
 
typedef lor_intensity(* lor_intensity_fn) (uint8_t b)
 Represents a function that converts an arbitrary byte value to a a scaled intensity value used by the LOR protocol.
 

Enumerations

enum  lor_effect {
  LOR_SET_LIGHTS = 0x1 , LOR_SET_OFF = 0x2 , LOR_SET_INTENSITY = 0x3 , LOR_FADE = 0x4 ,
  LOR_PULSE = 0x5 , LOR_TWINKLE = 0x6 , LOR_SHIMMER = 0x7 , LOR_SET_DMX_INTENSITY = 0x8
}
 Represents the various effects that may be applied to a set of channels on a specific unit. Each effect may require additional arguments, which are stored in the args field of the lor_req_s structure. Fields may be set directly, or better yet, by using the provided helper functions which handle potential data validation and conversion that you may not want to do. More...
 
enum  lor_channel_format {
  LOR_FMT_SINGLE = 0x00 , LOR_FMT_16 = 0x10 , LOR_FMT_8H = 0x20 , LOR_FMT_8L = 0x30 ,
  LOR_FMT_UNIT = 0x40 , LOR_FMT_MULTIPART = 0x50
}
 Represents the various formats that a channel set may be encoded in for the LOR protocol. The format is used to determine how the channel set is encoded into binary data for transmission. The format is determined by the number of channels in the set and the alignment of the first channel in the set. More...
 

Functions

void lor_unit_set_add (lor_unit_set *s, lor_unit unit)
 Adds a single unit ID to the set. Adding an ID that is already a member has no effect.
 
void lor_unit_set_all (lor_unit_set *s, const lor_unit *u, size_t us)
 Adds each unit ID in an array to the set.
 
void lor_unit_set_clear (lor_unit_set *s)
 Removes every unit ID from the set, leaving it empty. Also serves to initialize a set whose storage has not been zeroed.
 
void lor_set_channel (lor_req_s *req, lor_channel c)
 Configures the request to use a single channel, addressed by its 0-based index (index 0 is channel 1 in LOR software). The index is encoded as '0x80 | index' in the single-channel format, so the controller receives it directly.
 
void lor_set_channels (lor_req_s *req, lor_channel first, uint16_t cbits)
 Configures the request to use a channel set, in the form of a 16-bit bitset of channels, "starting at" the first channel offset used.
 
void lor_set_unit (lor_req_s *req, lor_unit u)
 Configures the request to be sent to, and accepted by, the specified unit. A unit is required for all requests. A magic value of 0xFF may be used to broadcast the request to all units.
 
void lor_set_units (lor_req_s *req, lor_unit_set *units)
 Configures the request to be sent to, and accepted by, every unit in the provided set, using the LOR_UNIT_ID_LIST addressing form. This replaces any unit previously configured with lor_set_unit. The encoded frame grows by one count byte plus one byte per member.
 
int lor_set_effect (lor_req_s *req, lor_effect e, const lor_effect_args_u *args)
 Configures the request to apply the specified effect. The effect may require additional arguments, which are provided in the args field as a union. If provided, the args field is copied into the request at which point the caller may safely discard the original args. Any non-NULL arguments will be copied into the request, even if the effect does not require them. This allows future expansion of usable effects without modifying the behavior of the function.
 
void lor_set_intensity (lor_req_s *req, lor_intensity i)
 Configures the request to set the intensity of the lights to the provided value.
 
void lor_set_fade (lor_req_s *req, lor_intensity start, lor_intensity end, lor_decisec ds)
 Configures the request to fade from one intensity to another over a specified duration in deciseconds.
 
size_t lor_write (uint8_t *b, size_t bs, const lor_req_s *r, size_t rs, size_t *wb)
 Encodes and writes up to rs requests to the provided buffer b as binary data. Requests are first encoded into a scratch buffer to ensure the buffer has enough space to hold the encoded data. The function will attempt to write as many requests as possible to the buffer, up to the provided request count.
 
lor_intensity lor_get_intensity (uint8_t b)
 Encodes a [0,0xFF] value into a roughly equivalent LOR intensity value (precision is lossy) that is compatible with the protocol.
 

Detailed Description

A tiny library for generating LOR protocol requests.

Macro Definition Documentation

◆ LOR_HEARTBEAT_BYTES

#define LOR_HEARTBEAT_BYTES   ((uint8_t[]) {0, 0xFF, 0x81, 0x56, 0})

The pre-defined binary representation of a LOR heartbeat message.

◆ LOR_HEARTBEAT_DELAY_MS

#define LOR_HEARTBEAT_DELAY_MS   500

The intended delay in milliseconds between sending LOR heartbeats.

◆ LOR_HEARTBEAT_DELAY_NS

#define LOR_HEARTBEAT_DELAY_NS   500000000

The intended delay in nanoseconds between sending LOR heartbeats.

◆ LOR_HEARTBEAT_SIZE

#define LOR_HEARTBEAT_SIZE   5

The length of the LOR heartbeat message LOR_HEARTBEAT_BYTES.

◆ LOR_UNIT_ID_ALL

#define LOR_UNIT_ID_ALL   0xFF

The broadcast unit ID. A request addressed to this value is executed by every unit on the bus.

◆ LOR_UNIT_ID_HOST

#define LOR_UNIT_ID_HOST   0xFE

The reply marker. Frames sent from a unit back to the host (e.g. the response to a version query) begin with this value in place of a unit ID. It is never a valid destination for a request.

◆ LOR_UNIT_ID_LIST

#define LOR_UNIT_ID_LIST   0xF2

The unit list address. It is followed on the wire by a count byte and that many unit IDs; every unit whose ID appears in the list executes the request. Set automatically by lor_set_units.

Typedef Documentation

◆ lor_channel

Represents a 0-based channel index, which is a unique identifier for a specific light or group of lights on a unit. Index 0 is the first channel (shown as channel 1 in LOR software), index 15 is the 16th. Valid indices are [0, 1023]. Indices 16 and above address additional 16-channel banks via the multipart channel format, which 16-channel controllers (e.g. CTB16PCg3) do not implement and silently discard.

◆ lor_channel_format

◆ lor_channel_set

◆ lor_decisec

Represents a duration in deciseconds, which is 1/10th of a second.

◆ lor_effect

typedef enum lor_effect lor_effect

◆ lor_effect_args_u

◆ lor_intensity

Represents a scaled intensity value used by the LOR protocol.

Note
The value must be first converted to a scaled intensity value before being passed to the LOR protocol.

◆ lor_intensity_fn

lor_intensity_fn

Represents a function that converts an arbitrary byte value to a a scaled intensity value used by the LOR protocol.

◆ lor_req_s

typedef struct lor_req lor_req_s

◆ lor_unit

Represents a unit ID, which is a unique identifier for a piece of LOR hardware. Valid unit IDs are [1, 0xF0] (1-240); several units may share an ID, in which case they all execute the request. Reserved values: 0xFF (LOR_UNIT_ID_ALL) broadcasts to every unit, 0xF2 (LOR_UNIT_ID_LIST) introduces a unit list (see lor_set_units), and 0xFE (LOR_UNIT_ID_HOST) marks replies sent from a unit to the host. 0x00 is the frame delimiter and must never be used. 0xF1 and 0xF3-0xFD are unassigned; the CTB16PCg3 drops frames sent to them.

◆ lor_unit_set

typedef struct lor_unit_set lor_unit_set

Enumeration Type Documentation

◆ lor_channel_format

Represents the various formats that a channel set may be encoded in for the LOR protocol. The format is used to determine how the channel set is encoded into binary data for transmission. The format is determined by the number of channels in the set and the alignment of the first channel in the set.

Enumerator
LOR_FMT_SINGLE 

Single channel.

LOR_FMT_16 

16-bit bitset of channels.

LOR_FMT_8H 

8-bit bitset of channels, high byte (9-16).

LOR_FMT_8L 

8-bit bitset of channels, low byte (1-8).

LOR_FMT_UNIT 

Unit number, no channels.

LOR_FMT_MULTIPART 

Multi-part channel set.

◆ lor_effect

enum lor_effect

Represents the various effects that may be applied to a set of channels on a specific unit. Each effect may require additional arguments, which are stored in the args field of the lor_req_s structure. Fields may be set directly, or better yet, by using the provided helper functions which handle potential data validation and conversion that you may not want to do.

Enumerator
LOR_SET_LIGHTS 

Set the lights to full intensity.

LOR_SET_OFF 

Turn the lights off.

LOR_SET_INTENSITY 

Set the lights to a specific intensity.

LOR_FADE 

Fade between two intensities over time.

LOR_PULSE 

Cycle the lights between two intensities.

LOR_TWINKLE 

Twinkle the lights using hardware controls.

LOR_SHIMMER 

Shimmer the lights using hardware controls.

LOR_SET_DMX_INTENSITY 

Write raw DMX protocol data.

Function Documentation

◆ lor_get_intensity()

lor_intensity lor_get_intensity ( uint8_t  b)

Encodes a [0,0xFF] value into a roughly equivalent LOR intensity value (precision is lossy) that is compatible with the protocol.

Note
This is a default implementation of the lor_intensity_fn type. It operates via a known truth table from protocol documentation. Other or custom implementations may be ideal for your specific use case.
Parameters
bThe byte value to convert.
Returns
The scaled intensity value.

◆ lor_set_channel()

void lor_set_channel ( lor_req_s *  req,
lor_channel  c 
)

Configures the request to use a single channel, addressed by its 0-based index (index 0 is channel 1 in LOR software). The index is encoded as '0x80 | index' in the single-channel format, so the controller receives it directly.

Note
The index is reduced modulo 1024. Indices 16 and above are split into a 16-channel bank offset and select the multipart format, which 16-channel controllers do not implement (the request is dropped).
Parameters
reqThe request to configure.
cThe 0-based channel index to apply the effect to, less than 1024.
Here is the caller graph for this function:

◆ lor_set_channels()

void lor_set_channels ( lor_req_s *  req,
lor_channel  first,
uint16_t  cbits 
)

Configures the request to use a channel set, in the form of a 16-bit bitset of channels, "starting at" the first channel offset used.

Note
Any bits within the set that (once re-aligned to a 16-bit boundary) exceed the 16-bit window, will be disregarded. Pre-aligned 16-bit bitsets are recommended for best results. You may set the request's cset offset and cbits fields directly.
Parameters
reqThe request to configure.
firstThe 0-based index of the first channel in the set, i.e. the channel selected by bit 0 of cbits (see lor_channel).
cbitsThe 16-bit bitset of channels to apply the effect to; bit n selects channel index first + n.
Here is the caller graph for this function:

◆ lor_set_effect()

int lor_set_effect ( lor_req_s *  req,
lor_effect  e,
const lor_effect_args_u *  args 
)

Configures the request to apply the specified effect. The effect may require additional arguments, which are provided in the args field as a union. If provided, the args field is copied into the request at which point the caller may safely discard the original args. Any non-NULL arguments will be copied into the request, even if the effect does not require them. This allows future expansion of usable effects without modifying the behavior of the function.

Parameters
reqThe request to configure.
eThe effect to apply.
argsThe effect arguments, required if effect is LOR_SET_INTENSITY, LOR_FADE, LOR_PULSE, or LOR_SET_DMX_INTENSITY. Should likely be NULL for other effect types.
Returns
0 on success, -1 for invalid arguments.
Here is the caller graph for this function:

◆ lor_set_fade()

void lor_set_fade ( lor_req_s *  req,
lor_intensity  start,
lor_intensity  end,
lor_decisec  ds 
)

Configures the request to fade from one intensity to another over a specified duration in deciseconds.

Note
Equivalent to calling lor_set_effect with LOR_FADE and effect arguments set to the provided start and end intensities and duration.
Parameters
reqThe request to configure.
startThe starting intensity.
endThe ending intensity.
dsThe duration of the fade in deciseconds.
Here is the call graph for this function:

◆ lor_set_intensity()

void lor_set_intensity ( lor_req_s *  req,
lor_intensity  i 
)

Configures the request to set the intensity of the lights to the provided value.

Note
Equivalent to calling lor_set_effect with LOR_SET_INTENSITY and effect arguments set to the provided intensity.
Parameters
reqThe request to configure.
iThe intensity to use. This value should likely pass through a intensity conversion function before being passed to this function.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lor_set_unit()

void lor_set_unit ( lor_req_s *  req,
lor_unit  u 
)

Configures the request to be sent to, and accepted by, the specified unit. A unit is required for all requests. A magic value of 0xFF may be used to broadcast the request to all units.

Parameters
reqThe request to configure.
uThe unit to send the request to, or 0xFF to broadcast to all units.
Here is the caller graph for this function:

◆ lor_set_units()

void lor_set_units ( lor_req_s *  req,
lor_unit_set *  units 
)

Configures the request to be sent to, and accepted by, every unit in the provided set, using the LOR_UNIT_ID_LIST addressing form. This replaces any unit previously configured with lor_set_unit. The encoded frame grows by one count byte plus one byte per member.

Note
The set is referenced, not copied; it must remain valid and unchanged until the request has been encoded with lor_write. The set must contain at least one unit: an empty set encodes a count byte of 0x00, which terminates the frame before the command byte.
Parameters
reqThe request to configure.
unitsThe set of unit IDs to send the request to.
Here is the caller graph for this function:

◆ lor_unit_set_add()

void lor_unit_set_add ( lor_unit_set *  s,
lor_unit  unit 
)

Adds a single unit ID to the set. Adding an ID that is already a member has no effect.

Parameters
sThe set to modify.
unitThe unit ID to add, in [1, 0xF0].
Here is the caller graph for this function:

◆ lor_unit_set_all()

void lor_unit_set_all ( lor_unit_set *  s,
const lor_unit *  u,
size_t  us 
)

Adds each unit ID in an array to the set.

Note
Equivalent to calling lor_unit_set_add once per element of u.
Parameters
sThe set to modify.
uThe array of unit IDs to add, each in [1, 0xF0].
usThe number of unit IDs in u.
Here is the caller graph for this function:

◆ lor_unit_set_clear()

void lor_unit_set_clear ( lor_unit_set *  s)

Removes every unit ID from the set, leaving it empty. Also serves to initialize a set whose storage has not been zeroed.

Parameters
sThe set to clear.
Here is the caller graph for this function:

◆ lor_write()

size_t lor_write ( uint8_t *  b,
size_t  bs,
const lor_req_s *  r,
size_t  rs,
size_t *  wb 
)

Encodes and writes up to rs requests to the provided buffer b as binary data. Requests are first encoded into a scratch buffer to ensure the buffer has enough space to hold the encoded data. The function will attempt to write as many requests as possible to the buffer, up to the provided request count.

Parameters
bThe buffer to write the encoded requests to.
bsThe size of b in bytes.
rThe requests to encode, an array of at least rs elements.
rsThe number of requests in r to encode.
wbWritten byte count accumulator, may be NULL.
Returns
The number of requests successfully written to the buffer. The size of the written requests in bytes is added to wb if it is not NULL.
Here is the call graph for this function:
Here is the caller graph for this function: