diff --git a/.github/workflows/check-arduino.yml b/.github/workflows/check-arduino.yml index 3e0d26c..e818685 100644 --- a/.github/workflows/check-arduino.yml +++ b/.github/workflows/check-arduino.yml @@ -16,10 +16,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Arduino Lint - uses: arduino/arduino-lint-action@v1 + uses: arduino/arduino-lint-action@v2 with: compliance: specification library-manager: update diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index b880357..ac696fc 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -35,42 +35,82 @@ jobs: platforms: | - name: arduino:avr softwareserial: true + artifact-name-suffix: arduino-avr-uno - fqbn: arduino:avr:mega platforms: | - name: arduino:avr softwareserial: true + artifact-name-suffix: arduino-avr-mega - fqbn: arduino:avr:leonardo platforms: | - name: arduino:avr softwareserial: true + artifact-name-suffix: arduino-avr-leonardo - fqbn: arduino:megaavr:nona4809 platforms: | - name: arduino:megaavr softwareserial: true + artifact-name-suffix: arduino-megaavr-nona4809 - fqbn: arduino:sam:arduino_due_x_dbg platforms: | - name: arduino:sam softwareserial: false + artifact-name-suffix: arduino-sam-arduino_due_x_dbg - fqbn: arduino:samd:mkrzero platforms: | - name: arduino:samd softwareserial: false - - fqbn: arduino:mbed_portenta:envie_m4 + artifact-name-suffix: arduino-samd-mkrzero + - fqbn: arduino:mbed_portenta:envie_m7:target_core=cm4 platforms: | - name: arduino:mbed_portenta softwareserial: false + artifact-name-suffix: arduino-mbed_portenta-envie_m7-target_core-cm4 - fqbn: arduino:mbed_portenta:envie_m7 platforms: | - name: arduino:mbed_portenta softwareserial: false + artifact-name-suffix: arduino-mbed_portenta-envie_m7 - fqbn: arduino:mbed_nano:nano33ble platforms: | - name: arduino:mbed_nano softwareserial: false + artifact-name-suffix: arduino-mbed_nano-nano33ble - fqbn: arduino:mbed_nano:nanorp2040connect platforms: | - name: arduino:mbed_nano softwareserial: false + artifact-name-suffix: arduino-mbed_nano-nanorp2040connect + - fqbn: arduino:mbed_nicla:nicla_vision + platforms: | + - name: arduino:mbed_nicla + softwareserial: false + artifact-name-suffix: arduino-mbed_nicla-nicla_vision + - fqbn: arduino:mbed_opta:opta + platforms: | + - name: arduino:mbed_opta + softwareserial: false + artifact-name-suffix: arduino-mbed_opta-opta + - fqbn: arduino:mbed_giga:giga + platforms: | + - name: arduino:mbed_giga + softwareserial: false + artifact-name-suffix: arduino-mbed_giga-giga + - fqbn: arduino:renesas_portenta:portenta_c33 + platforms: | + - name: arduino:renesas_portenta + softwareserial: false + artifact-name-suffix: arduino-renesas_portenta-portenta_c33 + - fqbn: arduino:renesas_uno:unor4wifi + platforms: | + - name: arduino:renesas_uno + softwareserial: false + artifact-name-suffix: arduino-renesas_uno-unor4wifi + - fqbn: arduino:esp32:nano_nora + platforms: | + - name: arduino:esp32 + softwareserial: false + artifact-name-suffix: arduino-esp32-nano_nora # Make board type-specific customizations to the matrix jobs include: @@ -86,7 +126,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Compile examples uses: arduino/compile-sketches@v1 @@ -106,8 +146,8 @@ jobs: sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} - name: Save sketches report as workflow artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: if-no-files-found: error path: ${{ env.SKETCHES_REPORTS_PATH }} - name: ${{ env.SKETCHES_REPORTS_PATH }} + name: sketches-report-${{ matrix.board.artifact-name-suffix }} diff --git a/.github/workflows/report-size-deltas.yml b/.github/workflows/report-size-deltas.yml index 652be5d..39e2a0a 100644 --- a/.github/workflows/report-size-deltas.yml +++ b/.github/workflows/report-size-deltas.yml @@ -20,5 +20,5 @@ jobs: - name: Comment size deltas reports to PRs uses: arduino/report-size-deltas@v1 with: - # The name of the workflow artifact created by the sketch compilation workflow - sketches-reports-source: sketches-reports + # Regex matching the names of the workflow artifacts created by the "Compile Examples" workflow + sketches-reports-source: ^sketches-report-.+ diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml index 3f6b03f..ef7d894 100644 --- a/.github/workflows/spell-check.yml +++ b/.github/workflows/spell-check.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Spell check uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 986bda6..53a9f54 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -27,11 +27,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Download JSON schema for labels configuration file id: download-schema - uses: carlosperate/download-file-action@v1 + uses: carlosperate/download-file-action@v2 with: file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json location: ${{ runner.temp }}/label-configuration-schema @@ -65,12 +65,12 @@ jobs: steps: - name: Download - uses: carlosperate/download-file-action@v1 + uses: carlosperate/download-file-action@v2 with: file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} - name: Pass configuration files to next job via workflow artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: | *.yaml @@ -105,16 +105,16 @@ jobs: echo "::set-output name=flag::--dry-run" - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Download configuration files artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{ env.CONFIGURATIONS_ARTIFACT }} path: ${{ env.CONFIGURATIONS_FOLDER }} - name: Remove unneeded artifact - uses: geekyeggo/delete-artifact@v1 + uses: geekyeggo/delete-artifact@v5 with: name: ${{ env.CONFIGURATIONS_ARTIFACT }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..687f872 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode/ + diff --git a/LICENSE b/LICENSE index cd4defc..f288702 100644 --- a/LICENSE +++ b/LICENSE @@ -1,17 +1,3 @@ -This file includes licensing information for Arduino_DebugUtils. - -Copyright (c) 2018 ARDUINO SA (www.arduino.cc) - -The software is released under the GNU General Public License, which covers the main body -of the Arduino_DebugUtils code. The terms of this license can be found at: -https://www.gnu.org/licenses/gpl-3.0.en.html - -You can be released from the requirements of the above licenses by purchasing -a commercial license. Buying such a license is mandatory if you want to modify or -otherwise use the software for commercial activities involving the Arduino -software without disclosing the source code of your own applications. To purchase -a commercial license, send an email to license@arduino.cc - GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -645,8 +631,8 @@ to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - Arduino_DebugUtils encapsulates functionality useful for debugging code via printf statements. - Copyright (C) Arduino SA, 2019, Author: Alexander Entinger + + Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -666,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: - Arduino_DebugUtils Copyright (C) 2019, Arduino SA + Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. diff --git a/README.md b/README.md index 8f08544..c59b804 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,9 @@ Example: ```C++ int i = 1; float pi = 3.1459; -Debug.print(DBG_VERBOSE, "i = %d, pi = %f", i, pi); +DEBUG_VERBOSE("i = %d, pi = %f", i, pi); ``` +**Note**: The output of floating point numbers (`%f`) does NOT work on [ArduinoCore-avr](https://github.com/arduino/ArduinoCore-avr). If desired, timestamps can be prefixed to the debug message. Timestamp output can be enabled and disabled via `timestampOn` and `timestampOff`. @@ -42,7 +43,7 @@ Parameter debug_level in order of lowest to highest priority are : `DBG_NONE`, ` Return type: void. Example: -``` +```C++ Debug.setDebugLevel(DBG_VERBOSE); ``` ### Debug.setDebugOutputStream(Stream * stream) : @@ -51,7 +52,7 @@ By default, Output Stream is Serial. In advanced cases other objects could be ot Return type: void. Example: -``` +```C++ SoftwareSerial mySerial(10, 11); // RX, TX Debug.setDebugOutputStream(&mySerial); ``` @@ -62,9 +63,9 @@ By default, printing timestamp is off, unless turned on using this function call Return type: void. Example: -``` +```C++ Debug.timestampOn(); -Debug.print(DBG_VERBOSE, "i = %d", i); //Output looks like : [ 21007 ] i = 21 +DBG_VERBOSE("i = %d", i); //Output looks like : [ 21007 ] i = 21 ``` ### Debug.timestampOff() : @@ -73,9 +74,9 @@ Calling this function switches off the timestamp in the `Debug.print()` function Return type: void. Example: -``` +```C++ Debug.timestampOff(); -Debug.print(DBG_VERBOSE, "i = %d", i); //Output looks like : i = 21 +DEBUG_VERBOSE("i = %d", i); //Output looks like : i = 21 ``` ### Debug.newlineOn() : @@ -84,7 +85,7 @@ By default, a newline is sent Return type: void. Example: -``` +```C++ Debug.newlineOn(); ``` @@ -94,7 +95,7 @@ By default a newline is sent. Call this to shut that functionality off. Return type: void. Example: -``` +```C++ Debug.timestampOff(); ``` @@ -105,8 +106,14 @@ This function prints the message if parameter `debug_level` in the `Debug.print( Return type: void. Example: -``` +```C++ Debug.setDebugLevel(DBG_VERBOSE); int i = 0; -Debug.print(DBG_VERBOSE, "DBG_VERBOSE i = %d", i); +DEBUG_VERBOSE("DBG_VERBOSE i = %d", i); ``` + +# License + +Arduino_DebugUtils is licensed under the GNU General Public License v3.0. + +You can be released from the requirements of the above license by purchasing a commercial license. Buying such a license is mandatory if you want to modify or otherwise use the software for commercial activities involving the Arduino software without disclosing the source code of your own applications. To purchase a commercial license, send an email to license@arduino.cc diff --git a/examples/Arduino_Debug_Advance/Arduino_Debug_Advance.ino b/examples/Arduino_Debug_Advance/Arduino_Debug_Advance.ino index 5837b52..dbc704c 100644 --- a/examples/Arduino_Debug_Advance/Arduino_Debug_Advance.ino +++ b/examples/Arduino_Debug_Advance/Arduino_Debug_Advance.ino @@ -24,7 +24,7 @@ void setup() { int i = 0; void loop() { - Debug.print(DBG_VERBOSE, "i = %d", i); + DEBUG_VERBOSE("i = %d", i); i++; delay(1000); } diff --git a/examples/Arduino_Debug_Basic/Arduino_Debug_Basic.ino b/examples/Arduino_Debug_Basic/Arduino_Debug_Basic.ino index ddfedfe..1806e90 100644 --- a/examples/Arduino_Debug_Basic/Arduino_Debug_Basic.ino +++ b/examples/Arduino_Debug_Basic/Arduino_Debug_Basic.ino @@ -8,7 +8,7 @@ void setup() { int i = 0; void loop() { - Debug.print(DBG_INFO, "i = %d", i); + DEBUG_INFO("i = %d", i); i++; delay(1000); } diff --git a/keywords.txt b/keywords.txt index e5c2020..d175771 100644 --- a/keywords.txt +++ b/keywords.txt @@ -17,6 +17,11 @@ setDebugOutputStream KEYWORD2 timestampOn KEYWORD2 timestampOff KEYWORD2 print KEYWORD2 +DEBUG_ERROR KEYWORD2 +DEBUG_WARNING KEYWORD2 +DEBUG_INFO KEYWORD2 +DEBUG_DEBUG KEYWORD2 +DEBUG_VERBOSE KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/library.properties b/library.properties index 8bbc786..b59e2da 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Arduino_DebugUtils -version=1.2.0 +version=1.4.0 author=Arduino maintainer=Arduino sentence=Debugging module with different debug levels, timestamps and printf-style output. diff --git a/src/Arduino_DebugUtils.cpp b/src/Arduino_DebugUtils.cpp index 7111715..270927b 100644 --- a/src/Arduino_DebugUtils.cpp +++ b/src/Arduino_DebugUtils.cpp @@ -35,6 +35,8 @@ static Stream * DEFAULT_OUTPUT_STREAM = &Serial; Arduino_DebugUtils::Arduino_DebugUtils() { timestampOff(); newlineOn(); + debugLabelOff(); + formatTimestampOff(); setDebugLevel(DEFAULT_DEBUG_LEVEL); setDebugOutputStream(DEFAULT_OUTPUT_STREAM); } @@ -47,6 +49,10 @@ void Arduino_DebugUtils::setDebugLevel(int const debug_level) { _debug_level = debug_level; } +int Arduino_DebugUtils::getDebugLevel() const { + return _debug_level; +} + void Arduino_DebugUtils::setDebugOutputStream(Stream * stream) { _debug_output_stream = stream; } @@ -59,6 +65,22 @@ void Arduino_DebugUtils::newlineOff() { _newline_on = false; } +void Arduino_DebugUtils::debugLabelOn() { + _print_debug_label = true; +} + +void Arduino_DebugUtils::debugLabelOff() { + _print_debug_label = false; +} + +void Arduino_DebugUtils::formatTimestampOn() { + _format_timestamp_on = true; +} + +void Arduino_DebugUtils::formatTimestampOff() { + _format_timestamp_on = false; +} + void Arduino_DebugUtils::timestampOn() { _timestamp_on = true; } @@ -72,6 +94,9 @@ void Arduino_DebugUtils::print(int const debug_level, const char * fmt, ...) if (!shouldPrint(debug_level)) return; + if (_print_debug_label) + printDebugLabel(debug_level); + if (_timestamp_on) printTimestamp(); @@ -86,6 +111,9 @@ void Arduino_DebugUtils::print(int const debug_level, const __FlashStringHelper if (!shouldPrint(debug_level)) return; + if (_print_debug_label) + printDebugLabel(debug_level); + if (_timestamp_on) printTimestamp(); @@ -102,6 +130,10 @@ void Arduino_DebugUtils::print(int const debug_level, const __FlashStringHelper ******************************************************************************/ void Arduino_DebugUtils::vPrint(char const * fmt, va_list args) { + + va_list args_copy; + va_copy(args_copy, args); + // calculate required buffer length int msg_buf_size = vsnprintf(nullptr, 0, fmt, args) + 1; // add one for null terminator #if __STDC_NO_VLA__ == 1 @@ -111,7 +143,8 @@ void Arduino_DebugUtils::vPrint(char const * fmt, va_list args) { char msg_buf[msg_buf_size]; #endif - vsnprintf(msg_buf, msg_buf_size, fmt, args); + vsnprintf(msg_buf, msg_buf_size, fmt, args_copy); + va_end(args_copy); if (_newline_on) { _debug_output_stream->println(msg_buf); @@ -127,11 +160,60 @@ void Arduino_DebugUtils::vPrint(char const * fmt, va_list args) { void Arduino_DebugUtils::printTimestamp() { - char timestamp[20]; - snprintf(timestamp, 20, "[ %lu ] ", millis()); + char timestamp[32]; + + if (_format_timestamp_on) + { + auto const msCount = millis(); + + uint16_t const milliseconds = msCount % 1000; // ms remaining when converted to seconds + uint16_t const allSeconds = msCount / 1000; // total number of seconds to calculate remaining values + + uint16_t const hours = allSeconds / 3600; // convert seconds to hours + uint16_t const secondsRemaining = allSeconds % 3600; // seconds left over + + uint16_t const minutes = secondsRemaining / 60 ; // convert seconds left over to minutes + uint16_t const seconds = secondsRemaining % 60; // seconds left over + + snprintf(timestamp, sizeof(timestamp), // "prints" formatted output to a char array (string) + "[ " + "%02d:" //HH: + "%02d:" //MM: + "%02d." //SS. + "%03d" //MMM + " ] ", + hours, + minutes, + seconds, + milliseconds + ); + } + else + { + snprintf(timestamp, sizeof(timestamp), "[ %lu ] ", millis()); + } + _debug_output_stream->print(timestamp); } +void Arduino_DebugUtils::printDebugLabel(int const debug_level) +{ + static char const * DEBUG_MODE_STRING[5] = + { + "[DBG_ERROR ] ", + "[DBG_WARNING] ", + "[DBG_INFO ] ", + "[DBG_DEBUG ] ", + "[DBG_VERBOSE] ", + }; + + bool is_valid_debug_level = (debug_level >= DBG_ERROR) && (debug_level <= DBG_VERBOSE); + if (!is_valid_debug_level) + return; + + _debug_output_stream->print(DEBUG_MODE_STRING[debug_level]); +} + bool Arduino_DebugUtils::shouldPrint(int const debug_level) const { return ((debug_level >= DBG_ERROR) && (debug_level <= DBG_VERBOSE) && (debug_level <= _debug_level)); @@ -142,6 +224,11 @@ bool Arduino_DebugUtils::shouldPrint(int const debug_level) const ******************************************************************************/ Arduino_DebugUtils Debug; + void setDebugMessageLevel(int const debug_level) { Debug.setDebugLevel(debug_level); } + +int getDebugMessageLevel() { + return Debug.getDebugLevel(); +} diff --git a/src/Arduino_DebugUtils.h b/src/Arduino_DebugUtils.h index b759534..73e6287 100644 --- a/src/Arduino_DebugUtils.h +++ b/src/Arduino_DebugUtils.h @@ -38,6 +38,7 @@ static int const DBG_DEBUG = 3; static int const DBG_VERBOSE = 4; void setDebugMessageLevel(int const debug_level); +int getDebugMessageLevel(); /****************************************************************************** CLASS DECLARATION @@ -50,6 +51,7 @@ class Arduino_DebugUtils { Arduino_DebugUtils(); void setDebugLevel(int const debug_level); + int getDebugLevel() const; void setDebugOutputStream(Stream * stream); @@ -59,6 +61,12 @@ class Arduino_DebugUtils { void newlineOn(); void newlineOff(); + void debugLabelOn(); + void debugLabelOff(); + + void formatTimestampOn(); + void formatTimestampOff(); + void print(int const debug_level, const char * fmt, ...); void print(int const debug_level, const __FlashStringHelper * fmt, ...); @@ -67,11 +75,14 @@ class Arduino_DebugUtils { bool _timestamp_on; bool _newline_on; + bool _print_debug_label; + bool _format_timestamp_on; int _debug_level; Stream * _debug_output_stream; void vPrint(char const * fmt, va_list args); void printTimestamp(); + void printDebugLabel(int const debug_level); bool shouldPrint(int const debug_level) const; }; @@ -82,4 +93,28 @@ class Arduino_DebugUtils { extern Arduino_DebugUtils Debug; +/************************************************************************************** + * DEFINE + **************************************************************************************/ + +#ifndef DEBUG_ERROR +# define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) +#endif + +#ifndef DEBUG_WARNING +# define DEBUG_WARNING(fmt, ...) Debug.print(DBG_WARNING, fmt, ## __VA_ARGS__) +#endif + +#ifndef DEBUG_INFO +# define DEBUG_INFO(fmt, ...) Debug.print(DBG_INFO, fmt, ## __VA_ARGS__) +#endif + +#ifndef DEBUG_DEBUG +# define DEBUG_DEBUG(fmt, ...) Debug.print(DBG_DEBUG, fmt, ## __VA_ARGS__) +#endif + +#ifndef DEBUG_VERBOSE +# define DEBUG_VERBOSE(fmt, ...) Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) +#endif + #endif /* ARDUINO_DEBUG_UTILS_H_ */