1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
// Copyright 2023 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
/*
    This API allows for basic profiling information to be printed out over console.
    Usage example:
        #include "basic_profiling.h"
        // Original code:
        matrix_task();
        // Delete the original, replace with the following (variant 1, automatic naming):
        PROFILE_CALL(1000, matrix_task());
        // Delete the original, replace with the following (variant 2, explicit naming):
        PROFILE_CALL_NAMED(1000, "matrix_task", {
            matrix_task();
        });
*/
#if defined(PROTOCOL_LUFA) || defined(PROTOCOL_VUSB)
#    define TIMESTAMP_GETTER TCNT0
#elif defined(PROTOCOL_CHIBIOS)
#    define TIMESTAMP_GETTER chSysGetRealtimeCounterX()
#elif defined(PROTOCOL_ARM_ATSAM)
#    error arm_atsam not currently supported
#else
#    error Unknown protocol in use
#endif
#ifndef CONSOLE_ENABLE
// Can't do anything if we don't have console output enabled.
#    define PROFILE_CALL_NAMED(count, name, call) \
        do {                                      \
        } while (0)
#else
#    define PROFILE_CALL_NAMED(count, name, call)                                                                         \
        do {                                                                                                              \
            static uint64_t inner_sum = 0;                                                                                \
            static uint64_t outer_sum = 0;                                                                                \
            uint32_t        start_ts;                                                                                     \
            static uint32_t end_ts;                                                                                       \
            static uint32_t write_location = 0;                                                                           \
            start_ts                       = TIMESTAMP_GETTER;                                                            \
            if (write_location > 0) {                                                                                     \
                outer_sum += start_ts - end_ts;                                                                           \
            }                                                                                                             \
            do {                                                                                                          \
                call;                                                                                                     \
            } while (0);                                                                                                  \
            end_ts = TIMESTAMP_GETTER;                                                                                    \
            inner_sum += end_ts - start_ts;                                                                               \
            ++write_location;                                                                                             \
            if (write_location >= ((uint32_t)count)) {                                                                    \
                uint32_t inner_avg = inner_sum / (((uint32_t)count) - 1);                                                 \
                uint32_t outer_avg = outer_sum / (((uint32_t)count) - 1);                                                 \
                dprintf("%s -- Percentage time spent: %d%%\n", (name), (int)(inner_avg * 100 / (inner_avg + outer_avg))); \
                inner_sum      = 0;                                                                                       \
                outer_sum      = 0;                                                                                       \
                write_location = 0;                                                                                       \
            }                                                                                                             \
        } while (0)
#endif // CONSOLE_ENABLE
#define PROFILE_CALL(count, call) PROFILE_CALL_NAMED(count, #call, call)