Compare commits
No commits in common. "e1db6c530f17e5a1de513db5bded379f0df9098d" and "4bec2c3c4203b091d5d63353e3318e1ca108d731" have entirely different histories.
e1db6c530f
...
4bec2c3c42
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) [year] [fullname]
|
||||
Copyright (c) 2025 Dominic Hoeglinger
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
72
README.md
72
README.md
@ -1,18 +1,67 @@
|
||||
```
|
||||
▌ ╬ ▗▄▄▖ ▗▄▄▄▖▗▄▄▄▖
|
||||
▐▐ ▐ ▐▌ ▐▌▐▌ █ Pocket Event Trace
|
||||
▌ ▌▌ ▐▛▀▘ ▐▛▀▀▘ █ A tiny tracing library
|
||||
═══▐══ ▐▌ ▐▙▄▄▖ █ ═════════════════════════════
|
||||
▓▓▓▓▓ ░░░ ███████ ███████ ████████
|
||||
▓ ▓ ▒ ░ ██ ██ ██ Streaming Event Trace
|
||||
▓ ▓ ▓ ░░ ███████ █████ ██ A tiny signal tracing library
|
||||
▓ ▓ ▒ ░ ██ ██ ██
|
||||
▓▓▓▓▓ ░░░ ███████ ███████ ██ Version 1.0.1 Alpha
|
||||
```
|
||||
|
||||
# Introduction
|
||||
|
||||
PET is a small (less than 1k implementation lines) tracing library written in C and is highly optimized for minimal data usage
|
||||
and aims to be easy to set up and use while also being flexible enough to be integrated in hard real time systems.
|
||||
PET is a small tracing library written in C99.
|
||||
It is highly optimized for minimal data usage and aims to be easy to use
|
||||
while also being flexible enough to be integrated in hard real time systems.
|
||||
|
||||
# How to use
|
||||
|
||||
PET requires the integrator to implement a few functions such as the timestamp and output functions in order to work.
|
||||
Apart from that, it is up to the specific use case how to stream data.
|
||||
In its simplest form, traces are processed with no real time demands on a dedicated interface.
|
||||
For more advanced usage, this library allows packets to be written, as the time budget allows,
|
||||
into any given buffer to send its contents via DMA to for instance a serial output.
|
||||
|
||||
Simple example on Arduino:
|
||||
|
||||
````c
|
||||
|
||||
#include "set.h"
|
||||
|
||||
// Basic implementation of output and timestamp retrieval
|
||||
void set_out(const char* const str, size_t len) { Serial.write(str, len); }
|
||||
uint32_t set_timestamp(void) { return micros(); }
|
||||
|
||||
// No concurrency protection needed
|
||||
void set_crit_on(uint32_t *h) {}
|
||||
void set_crit_off(const uint32_t h) {}
|
||||
|
||||
static const size_t s_tracesize = 256;
|
||||
static set_trace_t s_tracebuf[256];
|
||||
|
||||
void setup()
|
||||
{
|
||||
set_init(s_tracebuf, s_tracesize);
|
||||
set_enable(set_drop); // drop traces on full buffer
|
||||
|
||||
set_u8trace("Serial.Ready", 0, false);
|
||||
Serial.begin(921600);
|
||||
while (!Serial);
|
||||
set_u8trace("Serial.Ready", 1, false);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
unsigned sawtooth = 0;
|
||||
|
||||
if (sawtooth < 0xFFFF) sawtooth++;
|
||||
else sawtooth = 0;
|
||||
set_u32trace("Main.Sawtooth", sawtooth, false);
|
||||
|
||||
if (sawtooth == 4711) Serial.write("I can still be used with regular text.");
|
||||
|
||||
set_output(0, true); //send unlimited traces compressed
|
||||
set_diagtrace(); // add diagnostic traces
|
||||
}
|
||||
````
|
||||
|
||||
# Basic operating principle
|
||||
|
||||
@ -38,3 +87,14 @@ making the trace appear to coincide with the last trace which captured a timesta
|
||||
|
||||
The repository contains an example client application which captures packages and outputs the traces in a Value Change Dump.
|
||||
This script uses the PyVCD package which is the only dependency.
|
||||
Apart from that, this utility has every function integrated it'll need to decode a trace stream.
|
||||
It expects data via stdin, and displays any non-tracing traffic.
|
||||
|
||||
Example usage tracing remotely via SSH:
|
||||
````bash
|
||||
# Open /dev/ttyUSB0 via SSH and record to "trace.vcd" with timescale of 1 microsecond with diagnostics enabled
|
||||
ssh user@host -C "picocom -b 921600 /dev/ttyUSB0" | ./set_record.py -d trace.vcd -s ./Sources -t "1 us" --diagnostics
|
||||
````
|
||||
|
||||
The resulting VCD can be inspected with dedicated programs such as GTKwave.
|
||||
|
||||
|
||||
306
pet.c → set.c
306
pet.c → set.c
@ -23,14 +23,14 @@
|
||||
|
||||
#include "pet.h"
|
||||
|
||||
#define PET_NIBBLE_TO_HEX(nibble) ((nibble) < 10 ? (nibble) + '0' : (nibble) - 10 + 'A')
|
||||
#define PET_NIBBLE(value, nibble) ((value >> nibble) & 0xF)
|
||||
#define PET_BYTE(value, offset) (char)(((value >> (8 * offset)) & 0xFF))
|
||||
#define PET_ENCODE(value, nibble) (char)(PET_NIBBLE_TO_HEX(PET_NIBBLE(value, nibble)))
|
||||
#define PET_NELEMS(a) (sizeof(a) / sizeof(a[0]))
|
||||
#define PET_MACROPACK_FRAME_SIZE (2 * 8)
|
||||
#define PET_MACROPACK_SIZE(n) (PET_MACROPACK_FRAME_SIZE * n + (PET_MACROPACK_FRAME_SIZE * n) / 254 + 1 + n - 1)
|
||||
#define PET_MAX_RENDER_SIZE(n) (PET_MACROPACK_SIZE(n) + (PET_MACROPACK_SIZE(n) / 254) + 1)
|
||||
#define SET_NIBBLE_TO_HEX(nibble) ((nibble) < 10 ? (nibble) + '0' : (nibble) - 10 + 'A')
|
||||
#define SET_NIBBLE(value, nibble) ((value >> nibble) & 0xF)
|
||||
#define SET_BYTE(value, offset) (char)(((value >> (8 * offset)) & 0xFF))
|
||||
#define SET_ENCODE(value, nibble) (char)(SET_NIBBLE_TO_HEX(SET_NIBBLE(value, nibble)))
|
||||
#define SET_NELEMS(a) (sizeof(a) / sizeof(a[0]))
|
||||
#define SET_MACROPACK_FRAME_SIZE (2 * 8)
|
||||
#define SET_MACROPACK_SIZE(n) (SET_MACROPACK_FRAME_SIZE * n + (SET_MACROPACK_FRAME_SIZE * n) / 254 + 1 + n - 1)
|
||||
#define SET_MAX_RENDER_SIZE(n) (SET_MACROPACK_SIZE(n) + (SET_MACROPACK_SIZE(n) / 254) + 1)
|
||||
|
||||
#define FASTLZ1_MAX_COPY 32
|
||||
#define FASTLZ1_MAX_LEN 264 /* 256 + 8 */
|
||||
@ -44,43 +44,43 @@
|
||||
|
||||
typedef enum
|
||||
{
|
||||
pet_d1 = 0x11,
|
||||
pet_d2 = 0x12,
|
||||
pet_d4 = 0x14,
|
||||
pet_v1 = 0x21,
|
||||
pet_v2 = 0x22,
|
||||
pet_v4 = 0x24,
|
||||
pet_a1 = 0x31,
|
||||
pet_a2 = 0x32,
|
||||
pet_a4 = 0x34,
|
||||
pet_s4 = 0x44,
|
||||
pet_f4 = 0x54,
|
||||
pet_ev = 0x60,
|
||||
} pet_type_t;
|
||||
set_d1 = 0x11,
|
||||
set_d2 = 0x12,
|
||||
set_d4 = 0x14,
|
||||
set_v1 = 0x21,
|
||||
set_v2 = 0x22,
|
||||
set_v4 = 0x24,
|
||||
set_a1 = 0x31,
|
||||
set_a2 = 0x32,
|
||||
set_a4 = 0x34,
|
||||
set_s4 = 0x44,
|
||||
set_f4 = 0x54,
|
||||
set_ev = 0x60,
|
||||
} set_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
pet_packet_z = (1 << 0),
|
||||
} pet_packetflags_t;
|
||||
set_packet_z = (1 << 0),
|
||||
} set_packetflags_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* m_tag;
|
||||
uint16_t m_hash;
|
||||
} pet_hashcache_t;
|
||||
} set_hashcache_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint32_t u32value;
|
||||
#if (!PET_FLOAT_DISABLE)
|
||||
#if (!SET_FLOAT_DISABLE)
|
||||
float f32value;
|
||||
#endif
|
||||
} pet_convert_t;
|
||||
} set_convert_t;
|
||||
|
||||
static bool s_enabled = false;
|
||||
static uint32_t s_last_time = 0;
|
||||
pet_overflow_policy_t s_policy = pet_overwrite;
|
||||
static pet_trace_t* s_tracebuffer;
|
||||
set_overflow_policy_t s_policy = set_overwrite;
|
||||
static set_trace_t* s_tracebuffer;
|
||||
static size_t s_tracebuffer_size = 0;
|
||||
static size_t s_tracebuffer_head = 0;
|
||||
static size_t s_tracebuffer_tail = 0;
|
||||
@ -100,39 +100,39 @@ static uint32_t s_diag_avg_ctime_n = 0;
|
||||
static uint32_t s_diag_avg_rtime_total = 0;
|
||||
static uint32_t s_diag_avg_rtime_n = 0;
|
||||
|
||||
#if (PET_HASHCACHE_LINES > 0)
|
||||
static pet_hashcache_t s_hashcache[PET_HASHCACHE_LINES] = {0};
|
||||
#if (SET_HASHCACHE_LINES > 0)
|
||||
static set_hashcache_t s_hashcache[SET_HASHCACHE_LINES] = {0};
|
||||
static size_t s_hashcache_index = 0;
|
||||
#endif
|
||||
|
||||
size_t render_macropacket_payload(char buffer[], const size_t buffer_size, size_t n);
|
||||
static size_t frame_preamble(char buffer[], const size_t buffer_size);
|
||||
static size_t frame_epilouge(char buffer[], const size_t buffer_size);
|
||||
static size_t pack_frame(char packet_bytes[], const pet_trace_t* const p_packet);
|
||||
static size_t pack_frame(char packet_bytes[], const set_trace_t* const p_packet);
|
||||
static size_t ttyize_payload(char packet_buffer[], const size_t packet_size, const size_t buffer_size);
|
||||
static uint16_t bsd_hash(const char* const str, size_t n);
|
||||
static bool populate_time_delta_packet(const uint32_t timestamp, pet_trace_t* const p_trace);
|
||||
static void tracebuffer_add(const uint32_t timestamp, const pet_type_t type, const uint32_t value, const uint8_t sub, char const *tag);
|
||||
static bool populate_time_delta_packet(const uint32_t timestamp, set_trace_t* const p_trace);
|
||||
static void tracebuffer_add(const uint32_t timestamp, const set_type_t type, const uint32_t value, const uint8_t sub, char const *tag);
|
||||
size_t cobs_encode(uint8_t* dst, size_t dst_buf_len, const uint8_t* ptr, int len, uint8_t delim);
|
||||
static int fastlz1_compress(const void* input, int length, void* output);
|
||||
|
||||
void pet_init(pet_trace_t tracebuffer[], size_t ntraces)
|
||||
void set_init(set_trace_t tracebuffer[], size_t ntraces)
|
||||
{
|
||||
s_tracebuffer = tracebuffer;
|
||||
s_tracebuffer_size = ntraces;
|
||||
}
|
||||
|
||||
size_t pet_get_buffer_items(void)
|
||||
size_t set_get_buffer_items(void)
|
||||
{
|
||||
return s_tracebuffer_items;
|
||||
}
|
||||
|
||||
void pet_set_tty_mode(const bool enable)
|
||||
void set_tty_mode(const bool enable)
|
||||
{
|
||||
s_tty_enabled = enable;
|
||||
}
|
||||
|
||||
size_t pet_tty_rubout(char buffer[], const size_t buffer_size)
|
||||
size_t set_tty_rubout(char buffer[], const size_t buffer_size)
|
||||
{
|
||||
const size_t rubout_packet_size = 3 + s_tty_rubout_len + 3;
|
||||
size_t buffer_pos = 0;
|
||||
@ -153,25 +153,25 @@ size_t pet_tty_rubout(char buffer[], const size_t buffer_size)
|
||||
return buffer_pos;
|
||||
}
|
||||
|
||||
size_t pet_output(size_t n, const bool compress)
|
||||
size_t set_output(size_t n, const bool compress)
|
||||
{
|
||||
const size_t render_number_items = 4;
|
||||
const size_t render_max_size = PET_MAX_RENDER_SIZE(render_number_items);
|
||||
char packet_bytes[PET_MAX_RENDER_SIZE(4)] = {0};
|
||||
const size_t render_max_size = SET_MAX_RENDER_SIZE(render_number_items);
|
||||
char packet_bytes[SET_MAX_RENDER_SIZE(4)] = {0};
|
||||
size_t packet_size = 0;
|
||||
size_t i = 0;
|
||||
n = (n == 0) ? s_tracebuffer_size : n;
|
||||
|
||||
while ((s_tracebuffer_full || (s_tracebuffer_tail != s_tracebuffer_head)) && (i < n))
|
||||
{
|
||||
packet_size = pet_render(packet_bytes, render_max_size, render_number_items, compress);
|
||||
packet_size = set_render(packet_bytes, render_max_size, render_number_items, compress);
|
||||
i += render_number_items;
|
||||
|
||||
pet_out(packet_bytes, packet_size);
|
||||
set_out(packet_bytes, packet_size);
|
||||
}
|
||||
|
||||
packet_size = pet_tty_rubout(packet_bytes, render_max_size);
|
||||
pet_out(packet_bytes, packet_size);
|
||||
packet_size = set_tty_rubout(packet_bytes, render_max_size);
|
||||
set_out(packet_bytes, packet_size);
|
||||
|
||||
return i;
|
||||
}
|
||||
@ -181,7 +181,7 @@ size_t render_macropacket_payload(char buffer[], const size_t buffer_size, size_
|
||||
const size_t max_render_size = (8 + 1 + 1) * 2 - 1;
|
||||
char payload_buffer[8] = {0};
|
||||
char delimimter = 0x00;
|
||||
pet_trace_t timestamp_pack = {0};
|
||||
set_trace_t timestamp_pack = {0};
|
||||
size_t payload_size = 0;
|
||||
size_t i = 0;
|
||||
size_t buffer_pos = 0;
|
||||
@ -220,20 +220,20 @@ size_t render_macropacket_payload(char buffer[], const size_t buffer_size, size_
|
||||
return buffer_pos;
|
||||
}
|
||||
|
||||
size_t pet_render(char buffer[], const size_t buffer_size, const size_t n, const bool compress)
|
||||
size_t set_render(char buffer[], const size_t buffer_size, const size_t n, const bool compress)
|
||||
{
|
||||
const char delimimter = '\033';
|
||||
size_t n_elems = (n == 0) ? s_tracebuffer_items : n;
|
||||
n_elems = (s_tty_enabled && (n > 4)) ? 4 : n_elems;
|
||||
size_t render_max_size = PET_MAX_RENDER_SIZE(n_elems);
|
||||
uint32_t ticks_render_start = pet_timestamp();
|
||||
size_t render_max_size = SET_MAX_RENDER_SIZE(n_elems);
|
||||
uint32_t ticks_render_start = set_timestamp();
|
||||
char *final_payload_buffer = NULL;
|
||||
size_t final_payload_size = 0;
|
||||
|
||||
while ((buffer_size < (1 + (render_max_size * 2))) && (n_elems > 0))
|
||||
{
|
||||
n_elems--;
|
||||
render_max_size = PET_MAX_RENDER_SIZE(n_elems);
|
||||
render_max_size = SET_MAX_RENDER_SIZE(n_elems);
|
||||
}
|
||||
|
||||
if (n_elems == 0) return 0;
|
||||
@ -245,11 +245,11 @@ size_t pet_render(char buffer[], const size_t buffer_size, const size_t n, const
|
||||
|
||||
size_t compressed_size = macropack_payload_size + (macropack_payload_size*15)/100;
|
||||
char *compressed_buffer = &buffer[buffer_size - compressed_size];
|
||||
uint32_t ticks_comp_start = pet_timestamp();
|
||||
uint32_t ticks_comp_start = set_timestamp();
|
||||
compressed_size = fastlz1_compress(buffer, macropack_payload_size, compressed_buffer);
|
||||
final_payload_buffer = compressed_buffer;
|
||||
final_payload_size = compressed_size;
|
||||
s_diag_avg_ctime_total += pet_timestamp() - ticks_comp_start;
|
||||
s_diag_avg_ctime_total += set_timestamp() - ticks_comp_start;
|
||||
s_diag_avg_ctime_n++;
|
||||
|
||||
if (macropack_payload_size > 0)
|
||||
@ -272,7 +272,7 @@ size_t pet_render(char buffer[], const size_t buffer_size, const size_t n, const
|
||||
size_t out_pos = frame_preamble(buffer, buffer_size);
|
||||
|
||||
uint8_t flags = 0;
|
||||
if (compress) flags |= (uint8_t)pet_packet_z;
|
||||
if (compress) flags |= (uint8_t)set_packet_z;
|
||||
buffer[out_pos] = flags;
|
||||
out_pos++;
|
||||
|
||||
@ -290,54 +290,54 @@ size_t pet_render(char buffer[], const size_t buffer_size, const size_t n, const
|
||||
out_pos += payload_size;
|
||||
out_pos += frame_epilouge(&buffer[out_pos], buffer_size - out_pos);
|
||||
|
||||
s_diag_avg_rtime_total += pet_timestamp() - ticks_render_start;
|
||||
s_diag_avg_rtime_total += set_timestamp() - ticks_render_start;
|
||||
s_diag_avg_rtime_n++;
|
||||
|
||||
return out_pos;
|
||||
}
|
||||
|
||||
void pet_enable(const pet_overflow_policy_t policy)
|
||||
void set_enable(const set_overflow_policy_t policy)
|
||||
{
|
||||
s_policy = policy;
|
||||
s_enabled = true;
|
||||
}
|
||||
|
||||
void pet_disable(void)
|
||||
void set_disable(void)
|
||||
{
|
||||
s_enabled = false;
|
||||
}
|
||||
|
||||
void pet_clear(void)
|
||||
void set_clear(void)
|
||||
{
|
||||
s_tracebuffer_tail = s_tracebuffer_head;
|
||||
s_tracebuffer_full = false;
|
||||
}
|
||||
|
||||
void pet_diagtrace(void)
|
||||
void set_diagtrace(void)
|
||||
{
|
||||
const uint32_t buffer_health = ((s_tracebuffer_size - s_tracebuffer_items) * 0xFF)/s_tracebuffer_size;
|
||||
|
||||
pet_u32trace("PET.BufferItems", s_tracebuffer_items, false);
|
||||
pet_u8trace("PET.BufferHealth", (uint8_t)buffer_health, true);
|
||||
set_u32trace("PET.BufferItems", s_tracebuffer_items, false);
|
||||
set_u8trace("PET.BufferHealth", (uint8_t)buffer_health, true);
|
||||
|
||||
if (s_diag_avg_compression_n > 0)
|
||||
{
|
||||
const uint32_t average = s_diag_avg_compression_total / s_diag_avg_compression_n;
|
||||
pet_u8trace("PET.CompressionLevel", (uint8_t)average, true);
|
||||
set_u8trace("PET.CompressionLevel", (uint8_t)average, true);
|
||||
s_diag_avg_compression_total = 0;
|
||||
s_diag_avg_compression_n = 0;
|
||||
}
|
||||
|
||||
if (s_diag_items_sent > 0)
|
||||
{
|
||||
pet_u32trace("PET.ItemsSent", s_diag_items_sent, true);
|
||||
set_u32trace("PET.ItemsSent", s_diag_items_sent, true);
|
||||
s_diag_items_sent = 0;
|
||||
}
|
||||
|
||||
if (s_diag_avg_ctime_n > 0)
|
||||
{
|
||||
const uint32_t average = s_diag_avg_ctime_total / s_diag_avg_ctime_n;
|
||||
pet_u8trace("PET.CompressionTime", (uint8_t)average, true);
|
||||
set_u8trace("PET.CompressionTime", (uint8_t)average, true);
|
||||
s_diag_avg_ctime_total = 0;
|
||||
s_diag_avg_ctime_n = 0;
|
||||
}
|
||||
@ -346,147 +346,147 @@ void pet_diagtrace(void)
|
||||
if (s_diag_avg_rtime_n > 0)
|
||||
{
|
||||
const uint32_t average = s_diag_avg_rtime_total / s_diag_avg_rtime_n;
|
||||
pet_u8trace("PET.RenderTime", (uint8_t)average, true);
|
||||
set_u8trace("PET.RenderTime", (uint8_t)average, true);
|
||||
s_diag_avg_rtime_total = 0;
|
||||
s_diag_avg_rtime_n = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void pet_evtrace(const char* const tag, const bool skip_time)
|
||||
void set_evtrace(const char* const tag, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
tracebuffer_add(skip_time ? 0UL : pet_timestamp(), pet_ev, 1UL, 0U, tag);
|
||||
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_ev, 1UL, 0U, tag);
|
||||
}
|
||||
}
|
||||
|
||||
void pet_u8trace(const char* const tag, const uint8_t value, const bool skip_time)
|
||||
void set_u8trace(const char* const tag, const uint8_t value, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
tracebuffer_add(skip_time ? 0UL : pet_timestamp(), pet_v1, (uint32_t)value, 0U, tag);
|
||||
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v1, (uint32_t)value, 0U, tag);
|
||||
}
|
||||
}
|
||||
|
||||
void pet_u16trace(const char* const tag, const uint16_t value, const bool skip_time)
|
||||
void set_u16trace(const char* const tag, const uint16_t value, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
tracebuffer_add(skip_time ? 0UL : pet_timestamp(), pet_v2, (uint32_t)value, 0U, tag);
|
||||
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v2, (uint32_t)value, 0U, tag);
|
||||
}
|
||||
}
|
||||
|
||||
void pet_u32trace(const char* const tag, const uint32_t value, const bool skip_time)
|
||||
void set_u32trace(const char* const tag, const uint32_t value, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
tracebuffer_add(skip_time ? 0UL : pet_timestamp(), pet_v4, (uint32_t)value, 0U, tag);
|
||||
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v4, (uint32_t)value, 0U, tag);
|
||||
}
|
||||
}
|
||||
|
||||
void pet_s8trace(const char* const tag, const int8_t value, const bool skip_time)
|
||||
void set_s8trace(const char* const tag, const int8_t value, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
tracebuffer_add(skip_time ? 0UL : pet_timestamp(), pet_v1, (uint32_t)value, 0U, tag);
|
||||
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v1, (uint32_t)value, 0U, tag);
|
||||
}
|
||||
}
|
||||
|
||||
void pet_s16trace(const char* const tag, const int16_t value, const bool skip_time)
|
||||
void set_s16trace(const char* const tag, const int16_t value, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
tracebuffer_add(skip_time ? 0UL : pet_timestamp(), pet_v2, (uint32_t)value, 0U, tag);
|
||||
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v2, (uint32_t)value, 0U, tag);
|
||||
}
|
||||
}
|
||||
|
||||
void pet_s4trace(const char* const tag, const int32_t value, const bool skip_time)
|
||||
void set_s4trace(const char* const tag, const int32_t value, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
tracebuffer_add(skip_time ? 0UL : pet_timestamp(), pet_v4, (uint32_t)value, 0U, tag);
|
||||
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v4, (uint32_t)value, 0U, tag);
|
||||
}
|
||||
}
|
||||
|
||||
void pet_au8trace(const char* const tag, const uint8_t value[const], const uint8_t size, const bool skip_time)
|
||||
void set_au8trace(const char* const tag, const uint8_t value[const], const uint8_t size, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
const size_t ts = skip_time ? 0UL : pet_timestamp();
|
||||
const size_t ts = skip_time ? 0UL : set_timestamp();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
tracebuffer_add(ts, pet_a1, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
tracebuffer_add(ts, set_a1, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pet_au16trace(const char* const tag, const uint16_t value[const], const uint8_t size, const bool skip_time)
|
||||
void set_au16trace(const char* const tag, const uint16_t value[const], const uint8_t size, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
const size_t ts = skip_time ? 0UL : pet_timestamp();
|
||||
const size_t ts = skip_time ? 0UL : set_timestamp();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
tracebuffer_add(ts, pet_a2, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
tracebuffer_add(ts, set_a2, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pet_au32trace(const char* const tag, const uint32_t value[const], const uint8_t size, const bool skip_time)
|
||||
void set_au32trace(const char* const tag, const uint32_t value[const], const uint8_t size, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
const size_t ts = skip_time ? 0UL : pet_timestamp();
|
||||
const size_t ts = skip_time ? 0UL : set_timestamp();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
uint16_t sub = (i) | (size << 8);
|
||||
tracebuffer_add(ts, pet_a4, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
tracebuffer_add(ts, set_a4, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pet_as8trace(const char* const tag, const int8_t value[const], const uint8_t size, const bool skip_time)
|
||||
void set_as8trace(const char* const tag, const int8_t value[const], const uint8_t size, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
const size_t ts = skip_time ? 0UL : pet_timestamp();
|
||||
const size_t ts = skip_time ? 0UL : set_timestamp();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
tracebuffer_add(ts, pet_a1, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
tracebuffer_add(ts, set_a1, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pet_as16trace(const char* const tag, const int16_t value[const], const uint8_t size, const bool skip_time)
|
||||
void set_as16trace(const char* const tag, const int16_t value[const], const uint8_t size, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
const size_t ts = skip_time ? 0UL : pet_timestamp();
|
||||
const size_t ts = skip_time ? 0UL : set_timestamp();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
tracebuffer_add(ts, pet_a2, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
tracebuffer_add(ts, set_a2, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pet_as32trace(const char* const tag, const int32_t value[const], const uint8_t size, const bool skip_time)
|
||||
void set_as32trace(const char* const tag, const int32_t value[const], const uint8_t size, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
const size_t ts = skip_time ? 0UL : pet_timestamp();
|
||||
const size_t ts = skip_time ? 0UL : set_timestamp();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
uint16_t sub = (i) | (size << 8);
|
||||
tracebuffer_add(ts, pet_a4, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
tracebuffer_add(ts, set_a4, (uint32_t)value[i], (uint8_t)i, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pet_strtrace(const char* const tag, const char* const str, const bool skip_time)
|
||||
void set_strtrace(const char* const tag, const char* const str, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
const size_t ts = skip_time ? 0UL : pet_timestamp();
|
||||
const size_t ts = skip_time ? 0UL : set_timestamp();
|
||||
uint32_t packword = 0;
|
||||
uint8_t packindex = 0;
|
||||
for (size_t i = 0; str[i] != '\0'; ++i)
|
||||
@ -495,24 +495,24 @@ void pet_strtrace(const char* const tag, const char* const str, const bool skip_
|
||||
packword |= (str[i] << (8 * packindex));
|
||||
if (packindex == 3)
|
||||
{
|
||||
tracebuffer_add(ts, pet_s4, packword, (uint8_t)str[i + 1] == '\0', tag);
|
||||
tracebuffer_add(ts, set_s4, packword, (uint8_t)str[i + 1] == '\0', tag);
|
||||
packword = 0;
|
||||
}
|
||||
}
|
||||
if (packindex != 3)
|
||||
{
|
||||
tracebuffer_add(ts, pet_s4, packword, (uint8_t)true, tag);
|
||||
tracebuffer_add(ts, set_s4, packword, (uint8_t)true, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (!PET_FLOAT_DISABLE)
|
||||
void pet_f32trace(const char* const tag, const float value, const bool skip_time)
|
||||
#if (!SET_FLOAT_DISABLE)
|
||||
void set_f32trace(const char* const tag, const float value, const bool skip_time)
|
||||
{
|
||||
pet_convert_t converter = {.f32value = value };
|
||||
set_convert_t converter = {.f32value = value };
|
||||
if (s_enabled == true)
|
||||
{
|
||||
tracebuffer_add(skip_time ? 0UL : pet_timestamp(), pet_f4, converter.u32value, 0U, tag);
|
||||
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_f4, converter.u32value, 0U, tag);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -541,56 +541,56 @@ static size_t frame_epilouge(char buffer[], const size_t buffer_size)
|
||||
return pack_pos;
|
||||
}
|
||||
|
||||
static size_t pack_frame(char packet_bytes[], const pet_trace_t* const p_packet)
|
||||
static size_t pack_frame(char packet_bytes[], const set_trace_t* const p_packet)
|
||||
{
|
||||
size_t packet_size = 0;
|
||||
|
||||
packet_bytes[packet_size++] = (char)p_packet->m_type;
|
||||
switch ((pet_type_t)p_packet->m_type)
|
||||
switch ((set_type_t)p_packet->m_type)
|
||||
{
|
||||
case pet_v1:
|
||||
case pet_a1:
|
||||
case pet_d1:
|
||||
packet_bytes[packet_size++] = PET_BYTE(p_packet->m_value, 0);
|
||||
case set_v1:
|
||||
case set_a1:
|
||||
case set_d1:
|
||||
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 0);
|
||||
break;
|
||||
case pet_v2:
|
||||
case pet_a2:
|
||||
case pet_d2:
|
||||
packet_bytes[packet_size++] = PET_BYTE(p_packet->m_value, 0);
|
||||
packet_bytes[packet_size++] = PET_BYTE(p_packet->m_value, 1);
|
||||
case set_v2:
|
||||
case set_a2:
|
||||
case set_d2:
|
||||
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 0);
|
||||
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 1);
|
||||
break;
|
||||
case pet_v4:
|
||||
case pet_a4:
|
||||
case pet_s4:
|
||||
case pet_f4:
|
||||
case pet_d4:
|
||||
packet_bytes[packet_size++] = PET_BYTE(p_packet->m_value, 0);
|
||||
packet_bytes[packet_size++] = PET_BYTE(p_packet->m_value, 1);
|
||||
packet_bytes[packet_size++] = PET_BYTE(p_packet->m_value, 2);
|
||||
packet_bytes[packet_size++] = PET_BYTE(p_packet->m_value, 3);
|
||||
case set_v4:
|
||||
case set_a4:
|
||||
case set_s4:
|
||||
case set_f4:
|
||||
case set_d4:
|
||||
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 0);
|
||||
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 1);
|
||||
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 2);
|
||||
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 3);
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((pet_type_t)p_packet->m_type)
|
||||
switch ((set_type_t)p_packet->m_type)
|
||||
{
|
||||
case pet_a1:
|
||||
case pet_a2:
|
||||
case pet_a4:
|
||||
case pet_s4:
|
||||
case set_a1:
|
||||
case set_a2:
|
||||
case set_a4:
|
||||
case set_s4:
|
||||
packet_bytes[packet_size++] = (char)p_packet->m_sub;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((pet_type_t)p_packet->m_type)
|
||||
switch ((set_type_t)p_packet->m_type)
|
||||
{
|
||||
case pet_d1:
|
||||
case pet_d2:
|
||||
case pet_d4:
|
||||
case set_d1:
|
||||
case set_d2:
|
||||
case set_d4:
|
||||
break;
|
||||
default:
|
||||
const uint16_t hash_tag = bsd_hash(p_packet->m_tag, PET_MAX_TAG_LEN);
|
||||
packet_bytes[packet_size++] = PET_BYTE(hash_tag, 0);
|
||||
packet_bytes[packet_size++] = PET_BYTE(hash_tag, 1);
|
||||
const uint16_t hash_tag = bsd_hash(p_packet->m_tag, SET_MAX_TAG_LEN);
|
||||
packet_bytes[packet_size++] = SET_BYTE(hash_tag, 0);
|
||||
packet_bytes[packet_size++] = SET_BYTE(hash_tag, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -610,8 +610,8 @@ static size_t ttyize_payload(char packet_buffer[], const size_t packet_size, con
|
||||
{
|
||||
value = packet_buffer[(packet_size - i - 1)];
|
||||
backpos = (packet_size - i - 1) * 2;
|
||||
packet_buffer[backpos] = PET_ENCODE(value, 0);
|
||||
packet_buffer[backpos + 1] = PET_ENCODE(value, 4);
|
||||
packet_buffer[backpos] = SET_ENCODE(value, 0);
|
||||
packet_buffer[backpos + 1] = SET_ENCODE(value, 4);
|
||||
}
|
||||
|
||||
return tty_packet_size;
|
||||
@ -622,10 +622,10 @@ static uint16_t bsd_hash(const char* const str, size_t n)
|
||||
uint32_t checksum = 0;
|
||||
|
||||
if (str == NULL) return 0U;
|
||||
#if (PET_HASHCACHE_LINES > 0)
|
||||
for (size_t i = 0; i < PET_HASHCACHE_LINES; ++i)
|
||||
#if (SET_HASHCACHE_LINES > 0)
|
||||
for (size_t i = 0; i < SET_HASHCACHE_LINES; ++i)
|
||||
{
|
||||
size_t hash_index = (i + s_hashcache_index) % PET_HASHCACHE_LINES;
|
||||
size_t hash_index = (i + s_hashcache_index) % SET_HASHCACHE_LINES;
|
||||
if (s_hashcache[hash_index].m_tag == str)
|
||||
{
|
||||
return s_hashcache[hash_index].m_hash;
|
||||
@ -638,8 +638,8 @@ static uint16_t bsd_hash(const char* const str, size_t n)
|
||||
checksum += str[i];
|
||||
checksum &= 0xFFFF;
|
||||
}
|
||||
#if (PET_HASHCACHE_LINES > 0)
|
||||
s_hashcache_index = (s_hashcache_index + 1) % PET_HASHCACHE_LINES;
|
||||
#if (SET_HASHCACHE_LINES > 0)
|
||||
s_hashcache_index = (s_hashcache_index + 1) % SET_HASHCACHE_LINES;
|
||||
s_hashcache[s_hashcache_index].m_hash = checksum;
|
||||
s_hashcache[s_hashcache_index].m_tag = str;
|
||||
#endif
|
||||
@ -647,7 +647,7 @@ static uint16_t bsd_hash(const char* const str, size_t n)
|
||||
return checksum;
|
||||
}
|
||||
|
||||
static bool populate_time_delta_packet(const uint32_t timestamp, pet_trace_t* const p_trace)
|
||||
static bool populate_time_delta_packet(const uint32_t timestamp, set_trace_t* const p_trace)
|
||||
{
|
||||
const uint32_t dt = timestamp - s_last_time;
|
||||
uint16_t type = 0;
|
||||
@ -658,15 +658,15 @@ static bool populate_time_delta_packet(const uint32_t timestamp, pet_trace_t* co
|
||||
{
|
||||
if (dt > 0xFFFF)
|
||||
{
|
||||
type = pet_d4;
|
||||
type = set_d4;
|
||||
}
|
||||
else if (dt > 0xFF)
|
||||
{
|
||||
type = pet_d2;
|
||||
type = set_d2;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = pet_d1;
|
||||
type = set_d1;
|
||||
}
|
||||
|
||||
p_trace->m_type = type;
|
||||
@ -682,18 +682,18 @@ static bool populate_time_delta_packet(const uint32_t timestamp, pet_trace_t* co
|
||||
return false;
|
||||
}
|
||||
|
||||
static void tracebuffer_add(const uint32_t timestamp, const pet_type_t type, const uint32_t value, const uint8_t sub, char const *tag)
|
||||
static void tracebuffer_add(const uint32_t timestamp, const set_type_t type, const uint32_t value, const uint8_t sub, char const *tag)
|
||||
{
|
||||
const size_t insertion_pos = s_tracebuffer_head;
|
||||
uint32_t critical_h = 0UL;
|
||||
|
||||
if (s_tracebuffer_full == false || s_policy == pet_overwrite)
|
||||
if (s_tracebuffer_full == false || s_policy == set_overwrite)
|
||||
{
|
||||
pet_crit_on(&critical_h);
|
||||
set_crit_on(&critical_h);
|
||||
s_tracebuffer_head = (s_tracebuffer_head + 1) % s_tracebuffer_size;
|
||||
s_tracebuffer_full = (s_tracebuffer_head == s_tracebuffer_tail);
|
||||
s_tracebuffer_items++;
|
||||
pet_crit_off(critical_h);
|
||||
set_crit_off(critical_h);
|
||||
|
||||
s_tracebuffer[insertion_pos].m_type = (uint8_t)type;
|
||||
s_tracebuffer[insertion_pos].m_value = value;
|
||||
@ -758,7 +758,7 @@ static uint16_t flz_hash(uint32_t v) {
|
||||
}
|
||||
|
||||
|
||||
static void pet_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count)
|
||||
static void set_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count)
|
||||
{
|
||||
for(size_t i = 0; i < count; ++i)
|
||||
{
|
||||
@ -776,14 +776,14 @@ static uint32_t flz_cmp(const uint8_t* p, const uint8_t* q, const uint8_t* r) {
|
||||
static uint8_t* flz_literals(uint32_t runs, const uint8_t* src, uint8_t* dest) {
|
||||
while (runs >= FASTLZ1_MAX_COPY) {
|
||||
*dest++ = FASTLZ1_MAX_COPY - 1;
|
||||
pet_memcpy(dest, src, FASTLZ1_MAX_COPY);
|
||||
set_memcpy(dest, src, FASTLZ1_MAX_COPY);
|
||||
src += FASTLZ1_MAX_COPY;
|
||||
dest += FASTLZ1_MAX_COPY;
|
||||
runs -= FASTLZ1_MAX_COPY;
|
||||
}
|
||||
if (runs > 0) {
|
||||
*dest++ = runs - 1;
|
||||
pet_memcpy(dest, src, runs);
|
||||
set_memcpy(dest, src, runs);
|
||||
dest += runs;
|
||||
}
|
||||
return dest;
|
||||
@ -21,28 +21,28 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PET_H_INCLUDED_
|
||||
#define PET_H_INCLUDED_
|
||||
#ifndef SET_H_INCLUDED_
|
||||
#define SET_H_INCLUDED_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** Maxmum signal name / tag length considered for the identifying hash */
|
||||
#define PET_MAX_TAG_LEN (126)
|
||||
#define SET_MAX_TAG_LEN (126)
|
||||
|
||||
/** Number of cached hashes */
|
||||
#define PET_HASHCACHE_LINES (64)
|
||||
#define SET_HASHCACHE_LINES (64)
|
||||
|
||||
/** Switch to enable or disable floating point support */
|
||||
#define PET_FLOAT_DISABLE (false)
|
||||
#define SET_FLOAT_DISABLE (false)
|
||||
|
||||
/** Overflow policy for the tracebuffer */
|
||||
typedef enum
|
||||
{
|
||||
pet_overwrite, /**< Overwrite oldest samples */
|
||||
pet_drop /**< Drop newest samples */
|
||||
} pet_overflow_policy_t;
|
||||
set_overwrite, /**< Overwrite oldest samples */
|
||||
set_drop /**< Drop newest samples */
|
||||
} set_overflow_policy_t;
|
||||
|
||||
/** Element used to allocate the tracebuffer */
|
||||
typedef struct
|
||||
@ -52,52 +52,52 @@ typedef struct
|
||||
uint32_t m_value;
|
||||
uint8_t m_type;
|
||||
uint8_t m_sub;
|
||||
} pet_trace_t;
|
||||
} set_trace_t;
|
||||
|
||||
/** @brief Integration hook writing out a packet to the desired interface
|
||||
* @param[in] str Packet data
|
||||
* @param[in] len Packet data length
|
||||
* @return None
|
||||
*/
|
||||
void pet_out(const char* const str, size_t len);
|
||||
void set_out(const char* const str, size_t len);
|
||||
|
||||
/** @brief Integration hook for retrieving a timestamp
|
||||
* @return Timestamp value
|
||||
*/
|
||||
uint32_t pet_timestamp(void);
|
||||
uint32_t set_timestamp(void);
|
||||
|
||||
/** @brief Integration hook which locks the tracebuffer
|
||||
* This can be for instance a mutex or interrupt lock.
|
||||
* @param[out] h handle value which will be passed to the #pet_crit_off function
|
||||
* @param[out] h handle value which will be passed to the #set_crit_off function
|
||||
*/
|
||||
void pet_crit_on(uint32_t *h);
|
||||
void set_crit_on(uint32_t *h);
|
||||
|
||||
/** @brief Integration hook which locks the tracebuffer
|
||||
* This can be for instance a mutex or interrupt lock.
|
||||
* @param[in] h handle value set by #pet_crit_on
|
||||
* @param[in] h handle value set by #set_crit_on
|
||||
*/
|
||||
void pet_crit_off(const uint32_t h);
|
||||
void set_crit_off(const uint32_t h);
|
||||
|
||||
/** @brief Initializes PET with the provided trace buffer
|
||||
* @param[in] str Trace buffer array
|
||||
* @param[in] len Trace buffer array length
|
||||
* @return None
|
||||
*/
|
||||
void pet_init(pet_trace_t tracebuffer[], size_t ntraces);
|
||||
void set_init(set_trace_t tracebuffer[], size_t ntraces);
|
||||
|
||||
/** @brief Returns the current trace buffer utilization
|
||||
* @return Number of items used in the trace buffer
|
||||
*/
|
||||
size_t pet_get_buffer_items(void);
|
||||
size_t set_get_buffer_items(void);
|
||||
|
||||
/** @brief Enables or disables TTY mode
|
||||
* TTY mode esures packet output is friendly for interactive console usage without a client.
|
||||
* This means that at most 4 packets are sent at once, the data is encoded as hex digits
|
||||
* and position is restored with each transmit. To erase a transmitted packet, see pet_tty_rubout.
|
||||
* and position is restored with each transmit. To erase a transmitted packet, see set_tty_rubout.
|
||||
* @param[in] enable If true, enable TTY mode
|
||||
* @return None
|
||||
*/
|
||||
void pet_set_tty_mode(const bool enable);
|
||||
void set_tty_mode(const bool enable);
|
||||
|
||||
/** @brief Creates a rubout packet clearing the maximum amount of data transmitted in TTY mode.
|
||||
* This consists of a ANSI store, enough spaces to overwrite sent data and an ANSI restore.
|
||||
@ -105,31 +105,31 @@ void pet_set_tty_mode(const bool enable);
|
||||
* @param[in] buffer_size the size of the output buffer
|
||||
* @return The packet size written to the buffer
|
||||
*/
|
||||
size_t pet_tty_rubout(char buffer[], const size_t buffer_size);
|
||||
size_t set_tty_rubout(char buffer[], const size_t buffer_size);
|
||||
|
||||
/** @brief Enables tracing with the provided overflow policy
|
||||
* @param[in] policy Either overwrite to overwrite oldest trace, or drop to drop the newest sample
|
||||
* @return None
|
||||
*/
|
||||
void pet_enable(const pet_overflow_policy_t policy);
|
||||
void set_enable(const set_overflow_policy_t policy);
|
||||
|
||||
/** @brief Disables tracing
|
||||
* @return None
|
||||
*/
|
||||
void pet_disable(void);
|
||||
void set_disable(void);
|
||||
|
||||
/** @brief Clears the trace buffer deleting all captures samples
|
||||
* @return None
|
||||
*/
|
||||
void pet_clear(void);
|
||||
void set_clear(void);
|
||||
|
||||
/** @brief Render a set amount of tracebuffer items and write them out using pet_out
|
||||
/** @brief Render a set amount of tracebuffer items and write them out using set_out
|
||||
* This function is for basic usage where the output function writes into a managed stream such as stdout
|
||||
* @param[in] n Number of tracebuffer items to render, or 0 for the current size of the tracebuffer
|
||||
* @param[in] compress if true, render the packets compressed
|
||||
* @return None
|
||||
*/
|
||||
size_t pet_output(size_t n, const bool compress);
|
||||
size_t set_output(size_t n, const bool compress);
|
||||
|
||||
/** @brief Render a set amount of tracebuffer items and store them in the provided buffer
|
||||
* This advanced function is intended to be used with DMA buffers.
|
||||
@ -139,7 +139,7 @@ size_t pet_output(size_t n, const bool compress);
|
||||
* @param[in] compress if true, render the packets compressed
|
||||
* @return None
|
||||
*/
|
||||
size_t pet_render(char buffer[], const size_t buffer_size, const size_t n, const bool compress);
|
||||
size_t set_render(char buffer[], const size_t buffer_size, const size_t n, const bool compress);
|
||||
|
||||
/** @brief Adds diagnostic samples to the tracebuffer
|
||||
* Signals include:
|
||||
@ -151,14 +151,14 @@ size_t pet_render(char buffer[], const size_t buffer_size, const size_t n, const
|
||||
* - PET.ItemsSent:u32 - The number of items sent since the last call to this function
|
||||
* @return None
|
||||
*/
|
||||
void pet_diagtrace(void);
|
||||
void set_diagtrace(void);
|
||||
|
||||
/** @brief Trace an event
|
||||
* @param[in] tag Signal name of the trace
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_evtrace(const char* const tag, const bool skip_time);
|
||||
void set_evtrace(const char* const tag, const bool skip_time);
|
||||
|
||||
/** @brief Trace an u8 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -166,7 +166,7 @@ void pet_evtrace(const char* const tag, const bool skip_time);
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_u8trace(const char* const tag, const uint8_t value, const bool skip_time);
|
||||
void set_u8trace(const char* const tag, const uint8_t value, const bool skip_time);
|
||||
|
||||
/** @brief Trace an u16 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -174,7 +174,7 @@ void pet_u8trace(const char* const tag, const uint8_t value, const bool skip_tim
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_u16trace(const char* const tag, const uint16_t value, const bool skip_time);
|
||||
void set_u16trace(const char* const tag, const uint16_t value, const bool skip_time);
|
||||
|
||||
/** @brief Trace an u32 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -182,7 +182,7 @@ void pet_u16trace(const char* const tag, const uint16_t value, const bool skip_t
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_u32trace(const char* const tag, const uint32_t value, const bool skip_time);
|
||||
void set_u32trace(const char* const tag, const uint32_t value, const bool skip_time);
|
||||
|
||||
/** @brief Trace an s8 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -190,7 +190,7 @@ void pet_u32trace(const char* const tag, const uint32_t value, const bool skip_t
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_s8trace(const char* const tag, const int8_t value, const bool skip_time);
|
||||
void set_s8trace(const char* const tag, const int8_t value, const bool skip_time);
|
||||
|
||||
/** @brief Trace an s16 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -198,7 +198,7 @@ void pet_s8trace(const char* const tag, const int8_t value, const bool skip_time
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_s16trace(const char* const tag, const int16_t value, const bool skip_time);
|
||||
void set_s16trace(const char* const tag, const int16_t value, const bool skip_time);
|
||||
|
||||
/** @brief Trace an s32 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -206,7 +206,7 @@ void pet_s16trace(const char* const tag, const int16_t value, const bool skip_ti
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_s32trace(const char* const tag, const int32_t value, const bool skip_time);
|
||||
void set_s32trace(const char* const tag, const int32_t value, const bool skip_time);
|
||||
|
||||
/** @brief Trace an array of u8 values
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -215,7 +215,7 @@ void pet_s32trace(const char* const tag, const int32_t value, const bool skip_ti
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_au8trace(const char* const tag, const uint8_t value[const], const uint8_t size, const bool skip_time);
|
||||
void set_au8trace(const char* const tag, const uint8_t value[const], const uint8_t size, const bool skip_time);
|
||||
|
||||
/** @brief Trace an array of u16 values
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -224,7 +224,7 @@ void pet_au8trace(const char* const tag, const uint8_t value[const], const uint8
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_au16trace(const char* const tag, const uint16_t value[const], const uint8_t size, const bool skip_time);
|
||||
void set_au16trace(const char* const tag, const uint16_t value[const], const uint8_t size, const bool skip_time);
|
||||
|
||||
/** @brief Trace an array of u32 values
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -233,7 +233,7 @@ void pet_au16trace(const char* const tag, const uint16_t value[const], const uin
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_au32trace(const char* const tag, const uint32_t value[const], const uint8_t size, const bool skip_time);
|
||||
void set_au32trace(const char* const tag, const uint32_t value[const], const uint8_t size, const bool skip_time);
|
||||
|
||||
|
||||
/** @brief Trace an array of s8 values
|
||||
@ -243,7 +243,7 @@ void pet_au32trace(const char* const tag, const uint32_t value[const], const uin
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_as8trace(const char* const tag, const int8_t value[const], const uint8_t size, const bool skip_time);
|
||||
void set_as8trace(const char* const tag, const int8_t value[const], const uint8_t size, const bool skip_time);
|
||||
|
||||
/** @brief Trace an array of s16 values
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -252,7 +252,7 @@ void pet_as8trace(const char* const tag, const int8_t value[const], const uint8_
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_as16trace(const char* const tag, const int16_t value[const], const uint8_t size, const bool skip_time);
|
||||
void set_as16trace(const char* const tag, const int16_t value[const], const uint8_t size, const bool skip_time);
|
||||
|
||||
/** @brief Trace an array of s32 values
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -261,7 +261,7 @@ void pet_as16trace(const char* const tag, const int16_t value[const], const uint
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_as32trace(const char* const tag, const int32_t value[const], const uint8_t size, const bool skip_time);
|
||||
void set_as32trace(const char* const tag, const int32_t value[const], const uint8_t size, const bool skip_time);
|
||||
|
||||
/** @brief Trace a string
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -269,9 +269,9 @@ void pet_as32trace(const char* const tag, const int32_t value[const], const uint
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_strtrace(const char* const tag, const char* const str, const bool skip_time);
|
||||
void set_strtrace(const char* const tag, const char* const str, const bool skip_time);
|
||||
|
||||
#if (!PET_FLOAT_DISABLE)
|
||||
#if (!SET_FLOAT_DISABLE)
|
||||
|
||||
/** @brief Trace an f32 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
@ -279,7 +279,7 @@ void pet_strtrace(const char* const tag, const char* const str, const bool skip_
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void pet_f32trace(const char* const tag, const float value, const bool skip_time);
|
||||
void set_f32trace(const char* const tag, const float value, const bool skip_time);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -11,10 +11,11 @@ from vcd import VCDWriter, writer
|
||||
from vcd.common import VarType
|
||||
|
||||
header = """
|
||||
▌ ╬ ▗▄▄▖ ▗▄▄▄▖▗▄▄▄▖
|
||||
▐▐ ▐ ▐▌ ▐▌▐▌ █ Pocket Event Trace
|
||||
▌ ▌▌ ▐▛▀▘ ▐▛▀▀▘ █ VCD Recorder Utility
|
||||
═══▐══ ▐▌ ▐▙▄▄▖ █ CC BY-SA 2025 Dominic Höglinger
|
||||
▓▓▓▓▓ ░░░ ███████ ███████ ████████
|
||||
▓ ▓ ▒ ░ ██ ██ ██ Streaming Event Trace
|
||||
▓ ▓ ▓ ░░ ███████ █████ ██ VCD Recorder Utility
|
||||
▓ ▓ ▒ ░ ██ ██ ██
|
||||
▓▓▓▓▓ ░░░ ███████ ███████ ██ (c) 2025 D.Hoeglinger
|
||||
|
||||
"""
|
||||
|
||||
@ -197,7 +198,7 @@ def scan_for_signals(directory, predefined_signals):
|
||||
|
||||
return list(signals.values()), valid
|
||||
|
||||
class PetFilter:
|
||||
class Filter:
|
||||
PREAMBLE = b"\x1b[s"
|
||||
EPILOUGE = b"\x1b[u"
|
||||
TAGCODE_LUT = {
|
||||
@ -260,7 +261,6 @@ class PetFilter:
|
||||
|
||||
if tagcode not in self.TAGCODE_LUT:
|
||||
self.packets_dropped += 1
|
||||
print("LUT ERR", tagcode)
|
||||
return
|
||||
|
||||
tag = self.TAGCODE_LUT[tagcode]
|
||||
@ -325,7 +325,7 @@ class PetFilter:
|
||||
else:
|
||||
self.disassemble_packet(packet)
|
||||
|
||||
class PetRetagger:
|
||||
class Retagger:
|
||||
def __init__(self, on_value, tags=None):
|
||||
tags = tags or []
|
||||
self._tag_lut = {bsd_hash(tag):tag for tag in tags}
|
||||
@ -412,11 +412,13 @@ class VcdSink:
|
||||
timestamp = self.timestamp
|
||||
# unpack
|
||||
for i in range(0,4):
|
||||
char = chr(value >> (i*8) & 0xFF)
|
||||
self.strings[tag][1] += char
|
||||
char = value >> (i*8) & 0xFF
|
||||
if char != 0:
|
||||
self.strings[tag][1] += chr(char)
|
||||
# sub of 1 indicates end of string
|
||||
if sub == 1:
|
||||
try:
|
||||
string = self.strings[tag][1]
|
||||
#print(f"### {timestamp:012X} : {self.varnames[tag]} <= \"{self.strings[tag][1]}\"", flush=True)
|
||||
self.writer.change(self.strings[tag][0], timestamp, self.strings[tag][1])
|
||||
except ValueError:
|
||||
@ -504,9 +506,9 @@ def main():
|
||||
nfile = open(noisefile, 'wb')
|
||||
process_noise_p = partial(process_noise, nfile)
|
||||
|
||||
petv = VcdSink(dfile, signals, timescale)
|
||||
petr = PetRetagger(petv.process, tags)
|
||||
petf = PetFilter(petr.process, process_noise_p)
|
||||
vcd_sink = VcdSink(dfile, signals, timescale)
|
||||
retagger = Retagger(vcd_sink.process, tags)
|
||||
packet_filter = Filter(retagger.process, process_noise_p)
|
||||
print("Signals:")
|
||||
for var in signals:
|
||||
print(f" - {var}")
|
||||
@ -514,8 +516,8 @@ def main():
|
||||
|
||||
print(" === BEGIN NOISE ===")
|
||||
try:
|
||||
while True:
|
||||
for b in sys.stdin.buffer.read(1):
|
||||
for bstr in sys.stdin.buffer:
|
||||
for b in bstr:
|
||||
petf.process(b)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
@ -524,14 +526,14 @@ def main():
|
||||
print(" === END NOISE ===")
|
||||
print()
|
||||
|
||||
petv.writer.close()
|
||||
vcd_sink.writer.close()
|
||||
dfile.close()
|
||||
if nfile:
|
||||
nfile.close()
|
||||
|
||||
print("Summary:")
|
||||
packet_count = petf.packet_counter
|
||||
drop_count = petf.packets_dropped + petv.packets_dropped
|
||||
packet_count = packet_filter.packet_counter
|
||||
drop_count = packet_filter.packets_dropped + vcd_sink.packets_dropped
|
||||
trace_size = human_readable_size(os.path.getsize(tracefile))
|
||||
print(f" - Packets received: {packet_count}")
|
||||
print(f" - Packets dropped: {drop_count}")
|
||||
Loading…
x
Reference in New Issue
Block a user