26 #define CHAN_ACC_RAW_X 4
27 #define CHAN_ACC_RAW_Y 5
28 #define CHAN_ACC_RAW_Z 6
29 #define CHAN_ACC_CAL_X 7
30 #define CHAN_ACC_CAL_Y 8
31 #define CHAN_ACC_CAL_Z 9
32 #define CHAN_G_RAW_X 10
33 #define CHAN_G_RAW_Y 11
34 #define CHAN_G_RAW_Z 12
35 #define CHAN_G_CAL_X 13
36 #define CHAN_G_CAL_Y 14
37 #define CHAN_G_CAL_Z 15
38 #define CHAN_G_ALIGN_X 16
39 #define CHAN_G_ALIGN_Y 17
40 #define CHAN_G_ALIGN_Z 18
41 #define CHAN_OMEGA_X 19
42 #define CHAN_OMEGA_Y 20
43 #define CHAN_OMEGA_Z 21
47 #define CHAN_ACC_LIN_X 25
48 #define CHAN_ACC_LIN_Y 26
49 #define CHAN_ACC_LIN_Z 27
50 #define CHAN_ALTITUDE 28
63 if (lpmsInfo->
handle < 0) {
85 uint8_t rateData[4] = {
88 (lpmsInfo->
pollFreq & 0xFF0000) >> 16,
89 (lpmsInfo->
pollFreq & 0xFF000000) >> 24,
93 .length =
sizeof(uint32_t),
101 const uint32_t outputs =
106 uint8_t outputData[4] = {(outputs & 0xFF), (outputs & 0xFF00) >> 8,
107 (outputs & 0xFF0000) >> 16, (outputs & 0xFF000000) >> 24};
111 .length =
sizeof(uint32_t),
139 if (m == NULL) {
return false; }
167 uint8_t *buf = calloc(
LPMS_BUFF,
sizeof(uint8_t));
170 uint32_t outputs = 0;
171 bool unitMismatch =
false;
172 unsigned int pendingCount = 0;
173 unsigned int missingCount = 0;
178 perror(
"lpms_message calloc");
191 if ((m->
id != lpmsInfo->
unitID) && !unitMismatch) {
194 "[LPMS:%s] Unexpected unit ID (got 0x%02x, expected 0x%02x)",
200 ((uint32_t)m->
data[2] << 16) +
201 ((uint32_t)m->
data[3] << 24);
204 "[LPMS:%s] Output configuration received for unit 0x%02x",
208 "[LPMS:%s] Unit 0x%02x: Sensor model: %-24s", args->
tag,
211 int sl = asprintf(&lm,
"LPMS Unit 0x%02x: Sensor model: %-24s",
219 "[LPMS:%s] Error pushing message to queue",
227 "[LPMS:%s] Unit 0x%02x: Serial number: %-24s", args->
tag,
230 int sl = asprintf(&lm,
"LPMS Unit 0x%02x: Serial number: %-24s",
238 "[LPMS:%s] Error pushing message to queue",
246 "[LPMS:%s] Unit 0x%02x: Firmware version: %-24s",
249 int sl = asprintf(&lm,
"LPMS Unit 0x%02x: Firmware version: %-24s",
257 "[LPMS:%s] Error pushing message to queue",
264 uint32_t rate = m->
data[0] + ((uint32_t)m->
data[1] << 8) +
265 ((uint32_t)m->
data[2] << 16) +
266 ((uint32_t)m->
data[3] << 24);
268 "[LPMS:%s] Unit 0x%02x: Message rate %dHz", args->
tag,
273 if ((pendingCount++ % 100) == 0) {
276 "[LPMS:%s] No output configuration received - skipping messages (%d skipped so far)",
277 args->
tag, pendingCount);
279 "[LPMS:%s] Repeating GET_OUTPUTS request",
297 "[LPMS:%s] Error pushing message to queue",
307 "[LPMS:%s] Unit 0x%02x: Timestamp invalid",
328 if (missingCount == 0) {
331 "[LPMS:%s] Unit 0x%02x: Some data missing in update",
371 CHAN_OMEGA_X, d.
omega[0]);
373 CHAN_OMEGA_Y, d.
omega[1]);
375 CHAN_OMEGA_Z, d.
omega[2]);
393 "[LPMS:%s] Unable to allocate and/or queue all messages (%d)",
402 "[LPSM:%s] Unhandled message type: 0x%02x [%02d bytes]",
427 if (lpmsInfo->
handle >= 0) {
454 .
portName = NULL, .baudRate = 921600, .handle = -1, .unitID = 1, .pollFreq = 10};
474 log_error(args->
pstate,
"[LPMS:%s] Error pushing channel name to queue",
540 log_error(lta->
pstate,
"[LPMS:%s] Unable to allocate memory for device parameters",
560 int sn = strtol(t->
value, NULL, 0);
563 lta->
tag, strerror(errno));
580 "[LPMS:%s] Unexpected Source ID number (0x%02x)- this may cause analysis problems",
586 log_warning(lta->
pstate,
"[LPMS:%s] Source number not provided - 0x%02x assigned",
611 if ((lpmsInfo->
unitID <= 0) || (lpmsInfo->
unitID > 255)) {
613 "[LPMS:%s] Unit ID specified (%d not in range 1-255)", lta->
tag,
626 "[LPMS:%s] Error parsing minimum poll frequency: %s", lta->
tag,
643 "[LPMS:%s] Invalid minimum poll frequency (%d is not greater than zero)",
bool lpms_readMessage_buf(int handle, lpms_message *out, uint8_t buf[LPMS_BUFF], size_t *index, size_t *hw)
Read data from handle, and parse message if able.
bool lpms_send_command(const int handle, lpms_message *m)
Write command defined by structure to handle.
#define LPMS_BUFF
Default serial buffer allocation size.
int lpms_openConnection(const char *device, const int baud)
Open connection to an LPMS serial device.
bool lpms_send_stream_mode(const int handle)
Shortcut: Send LPMS_MSG_MODE_STREAM.
bool lpms_send_command_mode(const int handle)
Shortcut: Send LPMS_MSG_MODE_CMD.
bool lpms_checksum(const lpms_message *msg, uint16_t *csum)
Calculate checksum for LPMS message packet.
bool lpms_imu_set_gyro_aligned(const lpms_message *msg, lpms_data *d)
Extract gyro_aligned from lpms_message into lpms_data, if available.
bool lpms_imu_set_altitude(const lpms_message *msg, lpms_data *d)
Extract altitude from lpms_message into lpms_data, if available.
bool lpms_imu_set_euler_angles(const lpms_message *msg, lpms_data *d)
Extract euler_angles from lpms_message into lpms_data, if available.
bool lpms_imu_set_gyro_raw(const lpms_message *msg, lpms_data *d)
Extract gyro_raw from lpms_message into lpms_data, if available.
bool lpms_imu_set_accel_raw(const lpms_message *msg, lpms_data *d)
Extract accel_raw from lpms_message into lpms_data, if available.
bool lpms_imu_set_timestamp(const lpms_message *msg, lpms_data *d)
Extract timestamp from lpms_message into lpms_data, if available.
bool lpms_imu_set_accel_cal(const lpms_message *msg, lpms_data *d)
Extract accel_cal from lpms_message into lpms_data, if available.
bool lpms_imu_set_gyro_cal(const lpms_message *msg, lpms_data *d)
Extract gyro_cal from lpms_message into lpms_data, if available.
bool lpms_imu_set_accel_linear(const lpms_message *msg, lpms_data *d)
Extract accel_linear from lpms_message into lpms_data, if available.
bool lpms_imu_set_omega(const lpms_message *msg, lpms_data *d)
Extract omega from lpms_message into lpms_data, if available.
char * config_qstrdup(const char *c)
Duplicate string, stripping optional leading/trailing quote marks.
config_kv * config_get_key(const config_section *cs, const char *kn)
Find configugration key within specific section, by name.
void signalHandlersBlock(void)
Block signals that we have handlers for.
#define LPMS_IMU_EULER
euler[] will contain data
#define LPMS_IMU_ACCEL_LINEAR
accel_linear[] will contain data
#define LPMS_IMU_OMEGA
omega[] will contain data
#define LPMS_IMU_ACCEL_CAL
accel_cal[] will contain data
#define LPMS_IMU_GYRO_ALIGN
gyro_align[] will contain data
#define LPMS_IMU_ALTITUDE
altitude will contain data
#define LPMS_IMU_GYRO_CAL
gyro_cal[] will contain data
#define LPMS_IMU_GYRO_RAW
gyro_raw[] will contain data
#define LPMS_IMU_ACCEL_RAW
accel_raw[] will contain data
#define LPMS_MSG_SET_OUTPUTS
Configure fields included in IMUDATA messages.
#define LPMS_MSG_GET_OUTPUTS
Get fields configured for IMUDATA messages.
#define LPMS_MSG_GET_SERIALNUM
Get serial number as 24 character string.
#define LPMS_MSG_GET_FREQ
Get current streaming output rate.
#define LPMS_MSG_GET_IMUDATA
IMU data, as configured by LPMS_MSG_SET_OUTPUTS.
#define LPMS_MSG_GET_FIRMWAREVER
Get firmware version as 24 character string.
#define LPMS_MSG_GET_SENSORMODEL
Get hardware model as 24 character string.
#define LPMS_MSG_SET_FREQ
Set streaming output rate (Hz)
msg_t * msg_new_string(const uint8_t source, const uint8_t type, const size_t len, const char *str)
Create a new message with a single string embedded.
void msg_destroy(msg_t *msg)
Destroy a message.
msg_t * msg_new_string_array(const uint8_t source, const uint8_t type, const strarray *array)
Create a new message containing an array of strings.
msg_t * msg_new_timestamp(const uint8_t source, const uint8_t type, const uint32_t ts)
Create a timestamp message.
msg_t * msg_new_float(const uint8_t source, const uint8_t type, const float val)
Create new message with a single numeric value.
#define SLCHAN_TSTAMP
Source timestamp (milliseconds, arbitrary epoch)
#define SLCHAN_RAW
Raw device data (Not mandatory)
#define SLCHAN_LOG_INFO
Information messages.
#define SLCHAN_MAP
Channel name map (excludes log channels)
#define SLCHAN_NAME
Name of source device.
bool lpms_parseConfig(log_thread_args_t *lta, config_section *s)
Take a configuration section and parse parameters.
void * lpms_logging(void *ptargs)
Serial source main logging loop.
bool lpms_queue_message(msgqueue *Q, const uint8_t src, const uint8_t chan, const float val)
Helper function: Create and queue data messages, with error handling.
void * lpms_channels(void *ptargs)
Serial source channel map.
void * lpms_setup(void *ptargs)
Generic serial connection setup.
device_callbacks lpms_getCallbacks()
Fill out device callback functions for logging.
lpms_params lpms_getParams()
Fill out default MP source parameters.
void * lpms_shutdown(void *ptargs)
Serial source shutdown.
#define SLSOURCE_ADC
Generic analogue inputs.
atomic_bool shutdownFlag
Trigger clean software shutdown.
void log_info(const program_state *s, const int level, const char *format,...)
Output formatted information message at a given level.
void log_warning(const program_state *s, const char *format,...)
Output formatted warning message.
void log_error(const program_state *s, const char *format,...)
Output formatted error message.
bool queue_push(msgqueue *queue, msg_t *msg)
Add a message to the tail of the queue.
void sa_destroy(strarray *sa)
Destroy array and contents.
strarray * sa_new(int entries)
Allocate storage for a new array.
bool sa_create_entry(strarray *array, const int index, const size_t len, const char *src)
Create an string in a given position from a character array and length.
Represent a key=value pair.
char * value
Configuration item value.
Configuration file section.
Device specific function information.
device_fn startup
Called serially at startup, opens devices etc.
Logging thread information.
msgqueue * logQ
Main message queue. Pushed to by threads, consumed by main()
char * tag
Tag/source name for messages etc.
void * dParams
Device/Thread specific data.
program_state * pstate
Current program state, used for logging.
int returnCode
Thread return code (output)
float euler_angles[3]
Orientation as Euler roll angles [X].
float altitude
Altitude [m].
float gyro_aligned[3]
Calibrated and aligned gyroscope values [X/s].
float gyro_raw[3]
Raw gyroscope values [X/s].
float accel_linear[3]
Linear acceleration (only) [g].
uint32_t timestamp
Counted in 0.002s increments.
float accel_cal[3]
Calibrated accelerometer values [g].
float gyro_cal[3]
Calibrated gyroscope values [X/s].
float accel_raw[3]
Raw accelerometer values [g].
float omega[3]
Angular velocity [X/s].
uint32_t present
Bitmask indicating set/valid members.
uint16_t length
Length of data, in bytes.
uint16_t checksum
Sum of all preceding message bytes.
uint8_t * data
Pointer to data array.
uint16_t id
Source/Destination Sensor ID.
uint16_t command
Message type.
Serial device specific parameters.
int unitID
LPMS Sensor Address.
int pollFreq
Desired number of measurements per second.
int baudRate
Baud rate for operations (Default 921600)
int handle
Handle for currently opened device.
char * sourceName
User defined name for this source.
char * portName
Target port name.
uint8_t sourceNum
Source ID for messages.
Represent a simple FIFO message queue.