Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions doc/embedded/app_features/tdf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ one base reading, and then a repeating array of differences on each field. For e
} diffs[];
} __packed;

As long as the differences on each field fall within `int8_t` from the previous value, this can lead to
As long as the differences on each field fall within ``int8_t`` from the previous value, this can lead to
large packing efficiencies (75% in this example). The original values can be reconstructed as follows:

.. code-block:: c
Expand All @@ -162,26 +162,26 @@ encoding.
* - Enum
- Input Type
- Diff Type
* - :c:enumerator:`TDF_DIFF_16_8`
* - :c:enumerator:`TDF_DATA_FORMAT_DIFF_ARRAY_16_8`
- ``uint16_t`` / ``int16_t``
- ``int8_t``
* - :c:enumerator:`TDF_DIFF_32_8`
* - :c:enumerator:`TDF_DATA_FORMAT_DIFF_ARRAY_32_8`
- ``uint32_t`` / ``int32_t``
- ``int8_t``
* - :c:enumerator:`TDF_DIFF_32_16`
* - :c:enumerator:`TDF_DATA_FORMAT_DIFF_ARRAY_32_16`
- ``uint32_t`` / ``int32_t``
- ``int16_t``

The input data type defines how the encoder views the TDF struct, for example with
:c:enumerator:`TDF_DIFF_32_8` the encoder will interpret the input as ``uint32_t`` chunks.
:c:enumerator:`TDF_DATA_FORMAT_DIFF_ARRAY_32_8` the encoder will interpret the input as ``uint32_t`` chunks.
The diff type defines the maximum value difference between input chunks that can be
encoded as a valid diff.

Generally, the input data type will be self-evident from the TDF type being encoded. ``struct tdf_example``
from above for example should use either :c:enumerator:`TDF_DIFF_32_8` or :c:enumerator:`TDF_DIFF_32_16`.
The choice comes down to the expected differences between subsequent values. A larger diff type can
handle larger differences without falling back to :c:enumerator:`TDF_ARRAY_TIME`, but consumes more size
in the output buffer.
from above for example should use either :c:enumerator:`TDF_DATA_FORMAT_DIFF_ARRAY_32_8` or
:c:enumerator:`TDF_DATA_FORMAT_DIFF_ARRAY_32_16`. The choice comes down to the expected differences between
subsequent values. A larger diff type can handle larger differences without falling back to
:c:enumerator:`TDF_ARRAY_TIME`, but consumes more size in the output buffer.

When a reading is of this type, an additional 3 byte header is present after the timestamp structure.

Expand Down
32 changes: 16 additions & 16 deletions include/infuse/data_logger/high_level/tdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,17 @@ enum tdf_data_logger_mask {
* @param tdf_id TDF sensor ID
* @param tdf_len Length of a single TDF
* @param tdf_num Number of TDFs to add
* @param diff_type TDF diff encoding mode
* @param format TDF data encoding format
* @param time Epoch time associated with the first TDF. 0 for no timestamp.
* @param period Time period between the TDF samples
* @param data TDF data array
*
* @retval 0 On success
* @retval -errno Error code from @a tdf_add or @a tdf_data_logger_flush on error
*/
int tdf_data_logger_log_array_diff_dev(const struct device *dev, uint16_t tdf_id, uint8_t tdf_len,
uint8_t tdf_num, uint8_t diff_type, uint64_t time,
uint32_t period, const void *data);
int tdf_data_logger_log_core_dev(const struct device *dev, uint16_t tdf_id, uint8_t tdf_len,
uint8_t tdf_num, enum tdf_data_format format, uint64_t time,
uint32_t period, const void *data);

/**
* @brief Add multiple TDFs to multiple data loggers
Expand All @@ -90,14 +90,14 @@ int tdf_data_logger_log_array_diff_dev(const struct device *dev, uint16_t tdf_id
* @param tdf_id TDF sensor ID
* @param tdf_len Length of a single TDF
* @param tdf_num Number of TDFs to add
* @param diff_type TDF diff encoding mode
* @param format TDF data encoding format
* @param time Epoch time associated with the first TDF. 0 for no timestamp.
* @param period Time period between the TDF samples
* @param data TDF data array
*/
void tdf_data_logger_log_array_diff(uint8_t logger_mask, uint16_t tdf_id, uint8_t tdf_len,
uint8_t tdf_num, uint8_t diff_type, uint64_t time,
uint32_t period, const void *data);
void tdf_data_logger_log_core(uint8_t logger_mask, uint16_t tdf_id, uint8_t tdf_len,
uint8_t tdf_num, enum tdf_data_format format, uint64_t time,
uint32_t period, const void *data);

/**
* @brief Add multiple TDFs to a data logger
Expand All @@ -117,8 +117,8 @@ static inline int tdf_data_logger_log_array_dev(const struct device *dev, uint16
uint8_t tdf_len, uint8_t tdf_num, uint64_t time,
uint32_t period, const void *data)
{
return tdf_data_logger_log_array_diff_dev(dev, tdf_id, tdf_len, tdf_num, TDF_DIFF_NONE,
time, period, data);
return tdf_data_logger_log_core_dev(dev, tdf_id, tdf_len, tdf_num,
TDF_DATA_FORMAT_TIME_ARRAY, time, period, data);
}

/**
Expand All @@ -136,8 +136,8 @@ static inline void tdf_data_logger_log_array(uint8_t logger_mask, uint16_t tdf_i
uint8_t tdf_num, uint64_t time, uint32_t period,
const void *data)
{
tdf_data_logger_log_array_diff(logger_mask, tdf_id, tdf_len, tdf_num, TDF_DIFF_NONE, time,
period, data);
tdf_data_logger_log_core(logger_mask, tdf_id, tdf_len, tdf_num, TDF_DATA_FORMAT_TIME_ARRAY,
time, period, data);
}

/**
Expand All @@ -155,8 +155,8 @@ static inline void tdf_data_logger_log_array(uint8_t logger_mask, uint16_t tdf_i
static inline int tdf_data_logger_log_dev(const struct device *dev, uint16_t tdf_id,
uint8_t tdf_len, uint64_t time, const void *data)
{
return tdf_data_logger_log_array_diff_dev(dev, tdf_id, tdf_len, 1, TDF_DIFF_NONE, time, 0,
data);
return tdf_data_logger_log_core_dev(dev, tdf_id, tdf_len, 1, TDF_DATA_FORMAT_SINGLE, time,
0, data);
}

/**
Expand All @@ -171,8 +171,8 @@ static inline int tdf_data_logger_log_dev(const struct device *dev, uint16_t tdf
static inline void tdf_data_logger_log(uint8_t logger_mask, uint16_t tdf_id, uint8_t tdf_len,
uint64_t time, const void *data)
{
tdf_data_logger_log_array_diff(logger_mask, tdf_id, tdf_len, 1, TDF_DIFF_NONE, time, 0,
data);
tdf_data_logger_log_core(logger_mask, tdf_id, tdf_len, 1, TDF_DATA_FORMAT_SINGLE, time, 0,
data);
}

/**
Expand Down
27 changes: 13 additions & 14 deletions include/infuse/task_runner/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,24 +280,23 @@ static inline bool task_schedule_tdf_requested(const struct task_schedule *sched
* @param tdf_id TDF sensor ID
* @param tdf_len Length of a single TDF
* @param tdf_num Number of TDFs to log
* @param diff_type TDF diff encoding mode
* @param format TDF encoding mode
* @param time Epoch time associated with the first TDF. 0 for no timestamp.
* @param period Time period between the TDF samples
* @param data TDF data array
*/
static inline void task_schedule_tdf_log_array_diff(const struct task_schedule *schedule,
uint8_t tdf_mask, uint16_t tdf_id,
uint8_t tdf_len, uint8_t tdf_num,
uint8_t diff_type, uint64_t time,
uint32_t period, const void *data)
static inline void task_schedule_tdf_log_core(const struct task_schedule *schedule,
uint8_t tdf_mask, uint16_t tdf_id, uint8_t tdf_len,
uint8_t tdf_num, enum tdf_data_format format,
uint64_t time, uint32_t period, const void *data)
{
if (schedule->task_logging[0].tdf_mask & tdf_mask) {
tdf_data_logger_log_array_diff(schedule->task_logging[0].loggers, tdf_id, tdf_len,
tdf_num, diff_type, time, period, data);
tdf_data_logger_log_core(schedule->task_logging[0].loggers, tdf_id, tdf_len,
tdf_num, format, time, period, data);
}
if (schedule->task_logging[1].tdf_mask & tdf_mask) {
tdf_data_logger_log_array_diff(schedule->task_logging[1].loggers, tdf_id, tdf_len,
tdf_num, diff_type, time, period, data);
tdf_data_logger_log_core(schedule->task_logging[1].loggers, tdf_id, tdf_len,
tdf_num, format, time, period, data);
}
}

Expand All @@ -318,8 +317,8 @@ static inline void task_schedule_tdf_log_array(const struct task_schedule *sched
uint8_t tdf_num, uint64_t time, uint32_t period,
const void *data)
{
task_schedule_tdf_log_array_diff(schedule, tdf_mask, tdf_id, tdf_len, tdf_num,
TDF_DIFF_NONE, time, period, data);
task_schedule_tdf_log_core(schedule, tdf_mask, tdf_id, tdf_len, tdf_num,
TDF_DATA_FORMAT_TIME_ARRAY, time, period, data);
}

/**
Expand All @@ -336,8 +335,8 @@ static inline void task_schedule_tdf_log(const struct task_schedule *schedule, u
uint16_t tdf_id, uint8_t tdf_len, uint64_t time,
const void *data)
{
task_schedule_tdf_log_array_diff(schedule, tdf_mask, tdf_id, tdf_len, 1, TDF_DIFF_NONE,
time, 0, data);
task_schedule_tdf_log_core(schedule, tdf_mask, tdf_id, tdf_len, 1, TDF_DATA_FORMAT_SINGLE,
time, 0, data);
}

/**
Expand Down
44 changes: 21 additions & 23 deletions include/infuse/tdf/tdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,22 @@ struct tdf_buffer_state {
struct net_buf_simple buf;
};

enum tdf_data_type {
TDF_DATA_TYPE_SINGLE,
TDF_DATA_TYPE_TIME_ARRAY,
TDF_DATA_TYPE_DIFF_ARRAY,
} __packed;

enum tdf_diff_type {
TDF_DIFF_NONE = 0,
enum tdf_data_format {
/** Single sample */
TDF_DATA_FORMAT_SINGLE,
/** Time array with period */
TDF_DATA_FORMAT_TIME_ARRAY,
/** 16 bit data, 8 bit diffs */
TDF_DIFF_16_8 = 1,
TDF_DATA_FORMAT_DIFF_ARRAY_16_8,
/** 32 bit data, 8 bit diffs */
TDF_DIFF_32_8 = 2,
TDF_DATA_FORMAT_DIFF_ARRAY_32_8,
/** 32 bit data, 16 bit diffs */
TDF_DIFF_32_16 = 3,
/** Start of invalid values */
TDF_DIFF_INVALID,
TDF_DATA_FORMAT_DIFF_ARRAY_32_16,
/** Start of invalid range */
TDF_DATA_FORMAT_INVALID,
/** Data is already in [base, diff...] form */
TDF_DIFF_PRECOMPUTED = 0x80,
};
TDF_DATA_FORMAT_DIFF_PRECOMPUTED = 0x80,
} __packed;

struct tdf_parsed {
/** TDF time (0 for none) */
Expand All @@ -64,13 +61,11 @@ struct tdf_parsed {
/** Length of single TDF */
uint8_t tdf_len;
/** Data format */
enum tdf_data_type data_type;
enum tdf_data_format data_type;
union {
/** Number of TDFs */
uint8_t tdf_num;
struct {
/** Number of diff */
enum tdf_diff_type type;
/** Number of diffs */
uint8_t num;

Expand Down Expand Up @@ -146,7 +141,7 @@ static inline void tdf_buffer_state_reset(struct tdf_buffer_state *state)
}

/**
* @brief Add TDFs to memory buffer with diff encoding
* @brief Add TDFs to memory buffer with an explicit format
*
* @param state Pointer to current buffer state
* @param tdf_id TDF sensor ID
Expand All @@ -155,15 +150,15 @@ static inline void tdf_buffer_state_reset(struct tdf_buffer_state *state)
* @param time Epoch time associated with the first TDF. 0 for no timestamp.
* @param period Epoch time between tdfs when @a tdf_num > 0.
* @param data TDF data
* @param diff_type TDF diff type
* @param format Data encoding format
*
* @retval >0 Number of TDFs successfully added to buffer
* @retval -EINVAL Invalid arguments
* @retval -ENOSPC TDF too large to ever fit on buffer
* @retval -ENOMEM Insufficient space to add any TDFs to buffer
*/
int tdf_add_diff(struct tdf_buffer_state *state, uint16_t tdf_id, uint8_t tdf_len, uint8_t tdf_num,
uint64_t time, uint32_t period, const void *data, enum tdf_diff_type diff_type);
int tdf_add_core(struct tdf_buffer_state *state, uint16_t tdf_id, uint8_t tdf_len, uint8_t tdf_num,
uint64_t time, uint32_t period, const void *data, enum tdf_data_format format);

/**
* @brief Add TDFs to memory buffer
Expand All @@ -184,7 +179,10 @@ int tdf_add_diff(struct tdf_buffer_state *state, uint16_t tdf_id, uint8_t tdf_le
static inline int tdf_add(struct tdf_buffer_state *state, uint16_t tdf_id, uint8_t tdf_len,
uint8_t tdf_num, uint64_t time, uint32_t period, const void *data)
{
return tdf_add_diff(state, tdf_id, tdf_len, tdf_num, time, period, data, TDF_DIFF_NONE);
enum tdf_data_format format =
tdf_num > 1 ? TDF_DATA_FORMAT_TIME_ARRAY : TDF_DATA_FORMAT_SINGLE;

return tdf_add_core(state, tdf_id, tdf_len, tdf_num, time, period, data, format);
}

/**
Expand Down
43 changes: 23 additions & 20 deletions subsys/data_logger/high_level/tdf_data_logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,13 @@ int tdf_data_logger_remote_id_set(const struct device *dev, uint64_t remote_id)
#endif /* TDF_REMOTE_SUPPORT */

static int log_locked(const struct device *dev, uint16_t tdf_id, uint8_t tdf_len, uint8_t tdf_num,
uint8_t diff_type, uint64_t time, uint32_t period, const void *mem)
enum tdf_data_format format, uint64_t time, uint32_t period, const void *mem)
{
struct tdf_logger_data *data = dev->data;
int rc;

relog:
rc = tdf_add_diff(&data->tdf_state, tdf_id, tdf_len, tdf_num, time, period, mem, diff_type);
rc = tdf_add_core(&data->tdf_state, tdf_id, tdf_len, tdf_num, time, period, mem, format);
if (rc == -ENOMEM) {
LOG_DBG("%s no space, flush and retry", dev->name);
rc = flush_internal(dev, true);
Expand All @@ -247,7 +247,7 @@ static int log_locked(const struct device *dev, uint16_t tdf_id, uint8_t tdf_len
/* Logging precomputed diffs from a point other that the start is currently
* not supported.
*/
if (!(diff_type & TDF_DIFF_PRECOMPUTED)) {
if (!(format & TDF_DATA_FORMAT_DIFF_PRECOMPUTED)) {
goto relog;
}
}
Expand All @@ -262,9 +262,9 @@ static int log_locked(const struct device *dev, uint16_t tdf_id, uint8_t tdf_len
return rc;
}

int tdf_data_logger_log_array_diff_dev(const struct device *dev, uint16_t tdf_id, uint8_t tdf_len,
uint8_t tdf_num, uint8_t diff_type, uint64_t time,
uint32_t period, const void *mem)
int tdf_data_logger_log_core_dev(const struct device *dev, uint16_t tdf_id, uint8_t tdf_len,
uint8_t tdf_num, enum tdf_data_format format, uint64_t time,
uint32_t period, const void *mem)
{
const struct tdf_logger_config *config = dev->config;
struct tdf_logger_data *data = dev->data;
Expand All @@ -288,23 +288,23 @@ int tdf_data_logger_log_array_diff_dev(const struct device *dev, uint16_t tdf_id
}

k_sem_take(&data->lock, K_FOREVER);
rc = log_locked(dev, tdf_id, tdf_len, tdf_num, diff_type, time, period, mem);
rc = log_locked(dev, tdf_id, tdf_len, tdf_num, format, time, period, mem);
k_sem_give(&data->lock);
return rc < 0 ? rc : 0;
}

void tdf_data_logger_log_array_diff(uint8_t logger_mask, uint16_t tdf_id, uint8_t tdf_len,
uint8_t tdf_num, uint8_t diff_type, uint64_t time,
uint32_t period, const void *data)
void tdf_data_logger_log_core(uint8_t logger_mask, uint16_t tdf_id, uint8_t tdf_len,
uint8_t tdf_num, enum tdf_data_format format, uint64_t time,
uint32_t period, const void *data)
{
const struct device *dev;

/* Flush all loggers given */
do {
dev = logger_mask_iter(&logger_mask);
if (dev) {
(void)tdf_data_logger_log_array_diff_dev(dev, tdf_id, tdf_len, tdf_num,
diff_type, time, period, data);
(void)tdf_data_logger_log_core_dev(dev, tdf_id, tdf_len, tdf_num, format,
time, period, data);
}
} while (dev);
}
Expand All @@ -325,6 +325,8 @@ static void tdf_block_size_update(const struct device *logger, uint16_t block_si
const struct tdf_logger_config *config = dev->config;
struct tdf_logger_data *data = dev->data;
uint16_t limited = MIN(block_size, config->tdf_buffer_max_size);
bool is_diff;
uint8_t num;

k_sem_take(&data->lock, K_FOREVER);
LOG_DBG("%s: from %d to %d bytes", dev->name, data->tdf_state.buf.size, limited);
Expand Down Expand Up @@ -352,14 +354,15 @@ static void tdf_block_size_update(const struct device *logger, uint16_t block_si
#endif /* TDF_REMOTE_SUPPORT */
/* Re-log pending TDF's into the same buffer, which will flush as appropriate */
while (tdf_parse(&state, &tdf) == 0) {
uint8_t num = tdf.data_type == TDF_DATA_TYPE_DIFF_ARRAY
? 1 + tdf.diff_info.num
: tdf.tdf_num;
uint8_t diff_type = tdf.data_type == TDF_DATA_TYPE_DIFF_ARRAY
? TDF_DIFF_PRECOMPUTED | tdf.diff_info.type
: TDF_DIFF_NONE;

(void)log_locked(dev, tdf.tdf_id, tdf.tdf_len, num, diff_type, tdf.time,
is_diff = (tdf.data_type == TDF_DATA_FORMAT_DIFF_ARRAY_16_8) ||
(tdf.data_type == TDF_DATA_FORMAT_DIFF_ARRAY_32_8) ||
(tdf.data_type == TDF_DATA_FORMAT_DIFF_ARRAY_32_16);
num = is_diff ? 1 + tdf.diff_info.num : tdf.tdf_num;
if (is_diff) {
tdf.data_type |= TDF_DATA_FORMAT_DIFF_PRECOMPUTED;
}

(void)log_locked(dev, tdf.tdf_id, tdf.tdf_len, num, tdf.data_type, tdf.time,
tdf.period, tdf.data);
}
}
Expand Down
Loading
Loading