/* * PET: Pocket Event Trace - A tiny tracing library * 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 * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef SET_H_INCLUDED_ #define SET_H_INCLUDED_ #include #include #include /** Maxmum signal name / tag length considered for the identifying hash */ #define SET_MAX_TAG_LEN (126) /** Number of cached hashes */ #define SET_HASHCACHE_LINES (64) /** Switch to enable or disable floating point support */ #define SET_FLOAT_DISABLE (false) /** Overflow policy for the tracebuffer */ typedef enum { set_overwrite, /**< Overwrite oldest samples */ set_drop /**< Drop newest samples */ } set_overflow_policy_t; /** Element used to allocate the tracebuffer */ typedef struct { char const * m_tag; uint32_t m_timestamp; uint32_t m_value; uint8_t m_type; uint8_t m_sub; } 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 set_out(const char* const str, size_t len); /** @brief Integration hook for retrieving a timestamp * @return Timestamp value */ 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 #set_crit_off function */ 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 #set_crit_on */ 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 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 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 set_tty_rubout. * @param[in] enable If true, enable TTY mode * @return None */ 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. * @param[out] buffer output buffer to render the rubout packet * @param[in] buffer_size the size of the output buffer * @return The packet size written to the buffer */ 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 set_enable(const set_overflow_policy_t policy); /** @brief Disables tracing * @return None */ void set_disable(void); /** @brief Clears the trace buffer deleting all captures samples * @return None */ void set_clear(void); /** @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 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. * @param[out] buffer output buffer to render the packets * @param[in] buffer_size the size of the output buffer * @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 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: * - PET.BufferItems:u32 - The current amount of tracebuffer items * - PET.BufferHealth:u8 - The buffer utilization, zero means that the buffer is full while 255 means the buffer is free * - PET.CompressionLevel:u8 - The average compression level if packets are rendered compressed * - PET.CompressionTime:u32 - The average compression time spent for one packet render * - PET.RenderTime:u32 - The average render time for one packet * - PET.ItemsSent:u32 - The number of items sent since the last call to this function * @return None */ 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 set_evtrace(const char* const tag, const bool skip_time); /** @brief Trace an u8 value * @param[in] tag Signal name of the trace * @param[in] value Value to trace * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] value Value to trace * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] value Value to trace * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] value Value to trace * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] value Value to trace * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] value Value to trace * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] value Value array to trace * @param[in] size Size of the value array, must be an integer literal for the client to detect the signal correctly * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] value Value array to trace * @param[in] size Size of the value array, must be an integer literal for the client to detect the signal correctly * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] value Value array to trace * @param[in] size Size of the value array, must be an integer literal for the client to detect the signal correctly * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] tag Signal name of the trace * @param[in] value Value array to trace * @param[in] size Size of the value array, must be an integer literal for the client to detect the signal correctly * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] value Value array to trace * @param[in] size Size of the value array, must be an integer literal for the client to detect the signal correctly * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] value Value array to trace * @param[in] size Size of the value array, must be an integer literal for the client to detect the signal correctly * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ 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 * @param[in] str String to trace * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ void set_strtrace(const char* const tag, const char* const str, const bool skip_time); #if (!SET_FLOAT_DISABLE) /** @brief Trace an f32 value * @param[in] tag Signal name of the trace * @param[in] value Value to trace * @param[in] skip_time Use last recorded timestamp for this trace * @return None */ void set_f32trace(const char* const tag, const float value, const bool skip_time); #endif #endif