From 3008359b8fed685b050f987814f581c404a282e7 Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Thu, 11 Jun 2026 16:47:54 -0500 Subject: [PATCH 01/13] doc: Fix PDF doc build --- .github/workflows/build_and_publish_docs.yml | 7 ++- doc/Doxyfile | 6 ++- doc/conf_common.py | 6 --- doc/patch_doxygen_latex.py | 55 ++++++++++++++++++++ docker_build_docs.sh | 2 + 5 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 doc/patch_doxygen_latex.py diff --git a/.github/workflows/build_and_publish_docs.yml b/.github/workflows/build_and_publish_docs.yml index 461f7b827..34e343f47 100644 --- a/.github/workflows/build_and_publish_docs.yml +++ b/.github/workflows/build_and_publish_docs.yml @@ -35,15 +35,14 @@ jobs: cd doc # ignore if the following command fails build-docs -bs html -t esp32 -l en --project-path ../ --source-dir ./ --doxyfile_dir ./ || true + python3 patch_doxygen_latex.py _build/en/esp32/latex mkdir -p ../docs cp -r _build/en/esp32/html/* ../docs/. # go to the latex output cd _build/en/esp32/latex/ - # use xelatex because the generated docs include Unicode characters - # that pdflatex cannot render reliably - xelatex -interaction=batchmode refman || true + pdflatex -interaction=batchmode refman || true # build again to make sure page numbers and refs and such work (ignore if command fails) - xelatex -interaction=batchmode refman || true + pdflatex -interaction=batchmode refman || true if [ -f refman.pdf ]; then mv refman.pdf espp_documentation.pdf fi diff --git a/doc/Doxyfile b/doc/Doxyfile index c739531b3..29f2cd66c 100755 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -23,7 +23,11 @@ PROJECT_NAME = "Espressif++ (ESPP), an ESP C++ Library" ## QUIET = YES -INLINE_SOURCES = YES +# Keep inline sources out of the generated LaTeX/PDF output. Some example/source +# listings contain rich Unicode that is fine in code and HTML, but makes the +# standalone Doxygen PDF build unreliable. +INLINE_SOURCES = NO + # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those diff --git a/doc/conf_common.py b/doc/conf_common.py index b9593067c..e9b121279 100644 --- a/doc/conf_common.py +++ b/doc/conf_common.py @@ -22,9 +22,3 @@ idf_targets = ['esp32', 'esp32s2', 'esp32c3'] languages = ['en'] - -# The generated API/README content includes Unicode characters such as Ω, π, -# emoji, and other symbols that pdflatex cannot handle reliably. Use xelatex so -# the PDF docs build stays aligned with the HTML sources instead of requiring -# per-character LaTeX escape maintenance. -latex_engine = 'xelatex' diff --git a/doc/patch_doxygen_latex.py b/doc/patch_doxygen_latex.py new file mode 100644 index 000000000..d9ca81d4b --- /dev/null +++ b/doc/patch_doxygen_latex.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +from pathlib import Path +import sys + + +OLD_BLOCK = r"""\NewDocumentEnvironment{DoxyEnumFields}{O{2} m +b}{% + \par + \ifnum#1>2 + \DoxyParamTable{3}{lr}{#2}{#3} + \else + \DoxyParamTable{2}{l}{#2}{#3} + \fi +}{}""" + +NEW_BLOCK = r"""\NewDocumentEnvironment{DoxyEnumFields}{O{2} m +b}{% + \par + \begin{longtable}{|p{0.34\linewidth}|p{0.58\linewidth}|} + \hline + \textbf{#2} & \textbf{Description} \\ + \hline + \endfirsthead + \hline + \textbf{#2} & \textbf{Description} \\ + \hline + \endhead + #3 + \end{longtable} + \par\addvspace{6pt}% +}{}""" + + +def main() -> int: + if len(sys.argv) != 2: + print("usage: patch_doxygen_latex.py ", file=sys.stderr) + return 2 + + latex_dir = Path(sys.argv[1]) + style_path = latex_dir / "doxygen.sty" + if not style_path.exists(): + print(f"doxygen.sty not found in {latex_dir}", file=sys.stderr) + return 1 + + text = style_path.read_text() + if NEW_BLOCK in text: + return 0 + if OLD_BLOCK not in text: + print("expected DoxyEnumFields block not found in doxygen.sty", file=sys.stderr) + return 1 + + style_path.write_text(text.replace(OLD_BLOCK, NEW_BLOCK, 1)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/docker_build_docs.sh b/docker_build_docs.sh index a3199d622..9efd2c679 100755 --- a/docker_build_docs.sh +++ b/docker_build_docs.sh @@ -5,6 +5,8 @@ export PYTHONPATH=$PYTHONPATH:/project/doc git config --global --add safe.directory /project # build the docs build-docs -bs html -t esp32 -l en --project-path /project/ --source-dir /project/doc/ --doxyfile_dir /project/doc/ +# patch the generated Doxygen LaTeX so the PDF build can use pdflatex reliably +python3 /project/doc/patch_doxygen_latex.py /project/doc/_build/en/esp32/latex mkdir -p /project/docs # copy the docs to the docs folder cp -rf /project/_build/en/esp32/html/* /project/docs/. From 058601651a76a75dced2fcfc7598a0ef48901676 Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Fri, 12 Jun 2026 11:29:44 -0500 Subject: [PATCH 02/13] fix doc --- .github/workflows/build_and_publish_docs.yml | 18 +-- doc/build_latex_pdf.sh | 56 ++++++++ doc/patch_doxygen_latex.py | 128 +++++++++++++++---- docker_build_docs.sh | 7 +- 4 files changed, 166 insertions(+), 43 deletions(-) create mode 100755 doc/build_latex_pdf.sh diff --git a/.github/workflows/build_and_publish_docs.yml b/.github/workflows/build_and_publish_docs.yml index 34e343f47..bac90c5c9 100644 --- a/.github/workflows/build_and_publish_docs.yml +++ b/.github/workflows/build_and_publish_docs.yml @@ -35,23 +35,15 @@ jobs: cd doc # ignore if the following command fails build-docs -bs html -t esp32 -l en --project-path ../ --source-dir ./ --doxyfile_dir ./ || true - python3 patch_doxygen_latex.py _build/en/esp32/latex - mkdir -p ../docs - cp -r _build/en/esp32/html/* ../docs/. - # go to the latex output - cd _build/en/esp32/latex/ - pdflatex -interaction=batchmode refman || true - # build again to make sure page numbers and refs and such work (ignore if command fails) - pdflatex -interaction=batchmode refman || true - if [ -f refman.pdf ]; then - mv refman.pdf espp_documentation.pdf - fi - # set a variable to indicate whether the PDF was generated successfully - if [ -f espp_documentation.pdf ]; then + if sh ./build_latex_pdf.sh _build/en/esp32/latex; then echo "PDF_GENERATED=true" >> $GITHUB_ENV else + rm -f _build/en/esp32/latex/refman.pdf + rm -f _build/en/esp32/latex/espp_documentation.pdf echo "PDF_GENERATED=false" >> $GITHUB_ENV fi + mkdir -p ../docs + cp -r _build/en/esp32/html/* ../docs/. # warn if the PDF was not generated successfully if [ "$PDF_GENERATED" = "false" ]; then echo "Warning: PDF documentation was not generated successfully." diff --git a/doc/build_latex_pdf.sh b/doc/build_latex_pdf.sh new file mode 100755 index 000000000..4c578e0e3 --- /dev/null +++ b/doc/build_latex_pdf.sh @@ -0,0 +1,56 @@ +#!/bin/sh +set -eu + +if [ "$#" -ne 1 ]; then + echo "usage: build_latex_pdf.sh " >&2 + exit 2 +fi + +latex_dir=$1 +if [ ! -d "$latex_dir" ]; then + echo "latex directory not found: $latex_dir" >&2 + exit 1 +fi + +script_dir=$( + CDPATH= cd -- "$(dirname -- "$0")" && pwd +) + +success=0 +cleanup() { + if [ "$success" -ne 1 ]; then + rm -f "$latex_dir/refman.pdf" "$latex_dir/espp_documentation.pdf" + fi +} +trap cleanup EXIT HUP INT TERM + +rm -f \ + "$latex_dir/refman.pdf" \ + "$latex_dir/espp_documentation.pdf" \ + "$latex_dir/refman.aux" \ + "$latex_dir/refman.fdb_latexmk" \ + "$latex_dir/refman.fls" \ + "$latex_dir/refman.idx" \ + "$latex_dir/refman.ilg" \ + "$latex_dir/refman.ind" \ + "$latex_dir/refman.log" \ + "$latex_dir/refman.lof" \ + "$latex_dir/refman.lot" \ + "$latex_dir/refman.out" \ + "$latex_dir/refman.synctex.gz" \ + "$latex_dir/refman.toc" + +python3 "$script_dir/patch_doxygen_latex.py" "$latex_dir" + +cd "$latex_dir" +pdflatex -interaction=batchmode -halt-on-error refman.tex +python3 "$script_dir/patch_doxygen_latex.py" "$latex_dir" +pdflatex -interaction=batchmode -halt-on-error refman.tex + +if [ ! -s refman.pdf ]; then + echo "refman.pdf was not generated" >&2 + exit 1 +fi + +cp refman.pdf espp_documentation.pdf +success=1 diff --git a/doc/patch_doxygen_latex.py b/doc/patch_doxygen_latex.py index d9ca81d4b..5fc237114 100644 --- a/doc/patch_doxygen_latex.py +++ b/doc/patch_doxygen_latex.py @@ -1,33 +1,77 @@ #!/usr/bin/env python3 from pathlib import Path +import re import sys -OLD_BLOCK = r"""\NewDocumentEnvironment{DoxyEnumFields}{O{2} m +b}{% - \par - \ifnum#1>2 - \DoxyParamTable{3}{lr}{#2}{#3} - \else - \DoxyParamTable{2}{l}{#2}{#3} - \fi -}{}""" +OLD_NEWDOCUMENT_PATTERN = re.compile( + r"""\\NewDocumentEnvironment\{DoxyEnumFields\}\{O\{2\} m \+b\}\{\% +.*? +\}\{\}""", + re.DOTALL, +) -NEW_BLOCK = r"""\NewDocumentEnvironment{DoxyEnumFields}{O{2} m +b}{% - \par - \begin{longtable}{|p{0.34\linewidth}|p{0.58\linewidth}|} - \hline - \textbf{#2} & \textbf{Description} \\ - \hline - \endfirsthead - \hline - \textbf{#2} & \textbf{Description} \\ - \hline - \endhead - #3 - \end{longtable} - \par\addvspace{6pt}% +NEW_NEWDOCUMENT_BLOCK = r"""\NewDocumentEnvironment{DoxyEnumFields}{O{2} m +b}{% + \par + \begin{longtable}{|p{0.34\linewidth}|p{0.58\linewidth}|} + \hline + \multicolumn{2}{|l|}{\textbf{#2}} \\ + \hline + \endfirsthead + \hline + \multicolumn{2}{|l|}{\textbf{#2}} \\ + \hline + \endhead + #3 + \end{longtable} + \par\addvspace{6pt}% }{}""" +OLD_NEWENV_PATTERN = re.compile( + r"""\\newenvironment\{DoxyEnumFields\}\[1\]\{\% +.*? +\}\{\% +.*? +\}""", + re.DOTALL, +) + +NEW_NEWENV_BLOCK = r"""\newenvironment{DoxyEnumFields}[1]{% + \par% + \begin{longtable}{|p{0.34\linewidth}|p{0.58\linewidth}|}% + \hline% + \multicolumn{2}{|l|}{\textbf{#1}}\\% + \hline% + \endfirsthead% + \hline% + \multicolumn{2}{|l|}{\textbf{#1}}\\% + \hline% + \endhead% +}{% + \end{longtable}% + \vspace{6pt}% +}""" + +ETOC_LINE = ( + r"\IfFormatAtLeastTF{2023/05/01}{\usepackage[deeplevels]{etoc}}" + r"{\usepackage[deeplevels]{etoc_doxygen}}" +) +ETOC_REPLACEMENT = r"\usepackage[deeplevels]{etoc_doxygen}" +TOC_PRELUDE_PREFIX = r"\@ifundefined {etoctocstyle}" +ETOC_BLOCK_PATTERN = re.compile( + r""" % in page table of contents + .*? + \\etocsetlevel\{subparagraph\}\{9\} +""", + re.DOTALL, +) +ETOC_BLOCK_REPLACEMENT = """ % printed table of contents disabled for PDF stability on large manuals +""" +TABLE_OF_CONTENTS_LINE = r" \tableofcontents" +TABLE_OF_CONTENTS_REPLACEMENT = ( + " % printed table of contents disabled for PDF stability on large manuals" +) + def main() -> int: if len(sys.argv) != 2: @@ -41,13 +85,41 @@ def main() -> int: return 1 text = style_path.read_text() - if NEW_BLOCK in text: - return 0 - if OLD_BLOCK not in text: - print("expected DoxyEnumFields block not found in doxygen.sty", file=sys.stderr) - return 1 + if NEW_NEWDOCUMENT_BLOCK in text or NEW_NEWENV_BLOCK in text: + replacements = 0 + updated_text = text + else: + updated_text, replacements = OLD_NEWDOCUMENT_PATTERN.subn( + lambda _: NEW_NEWDOCUMENT_BLOCK, text, count=1 + ) + if replacements == 0: + updated_text, replacements = OLD_NEWENV_PATTERN.subn( + lambda _: NEW_NEWENV_BLOCK, text, count=1 + ) + if replacements == 0: + print("expected DoxyEnumFields block not found in doxygen.sty", file=sys.stderr) + return 1 + + style_path.write_text(updated_text) + + refman_path = latex_dir / "refman.tex" + if refman_path.exists(): + refman_text = refman_path.read_text() + if ETOC_LINE in refman_text: + refman_path.write_text(refman_text.replace(ETOC_LINE, ETOC_REPLACEMENT, 1)) + refman_text = refman_path.read_text() + refman_text, _ = ETOC_BLOCK_PATTERN.subn(ETOC_BLOCK_REPLACEMENT, refman_text, count=1) + if TABLE_OF_CONTENTS_LINE in refman_text: + refman_text = refman_text.replace( + TABLE_OF_CONTENTS_LINE, TABLE_OF_CONTENTS_REPLACEMENT, 1 + ) + refman_path.write_text(refman_text) - style_path.write_text(text.replace(OLD_BLOCK, NEW_BLOCK, 1)) + toc_path = latex_dir / "refman.toc" + if toc_path.exists(): + toc_lines = toc_path.read_text().splitlines(keepends=True) + if toc_lines and toc_lines[0].startswith(TOC_PRELUDE_PREFIX): + toc_path.write_text("".join(toc_lines[1:])) return 0 diff --git a/docker_build_docs.sh b/docker_build_docs.sh index 9efd2c679..9d5896cac 100755 --- a/docker_build_docs.sh +++ b/docker_build_docs.sh @@ -5,8 +5,11 @@ export PYTHONPATH=$PYTHONPATH:/project/doc git config --global --add safe.directory /project # build the docs build-docs -bs html -t esp32 -l en --project-path /project/ --source-dir /project/doc/ --doxyfile_dir /project/doc/ -# patch the generated Doxygen LaTeX so the PDF build can use pdflatex reliably -python3 /project/doc/patch_doxygen_latex.py /project/doc/_build/en/esp32/latex +if ! sh /project/doc/build_latex_pdf.sh /project/_build/en/esp32/latex; then + rm -f /project/_build/en/esp32/latex/refman.pdf + rm -f /project/_build/en/esp32/latex/espp_documentation.pdf + echo "Warning: PDF documentation was not generated successfully." >&2 +fi mkdir -p /project/docs # copy the docs to the docs folder cp -rf /project/_build/en/esp32/html/* /project/docs/. From 3bb0b4d1cfd56cc3b0ba1bf9e56298c07c5ef71c Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Fri, 12 Jun 2026 13:44:57 -0500 Subject: [PATCH 03/13] minor cleanup --- .github/workflows/build_and_publish_docs.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_and_publish_docs.yml b/.github/workflows/build_and_publish_docs.yml index bac90c5c9..2c412aef2 100644 --- a/.github/workflows/build_and_publish_docs.yml +++ b/.github/workflows/build_and_publish_docs.yml @@ -30,11 +30,18 @@ jobs: sudo apt-get install doxygen graphviz texlive-full pandoc pip install -r doc/requirements.txt - - name: Build Documentation + - name: Build Documentation (HTML) run: | cd doc # ignore if the following command fails build-docs -bs html -t esp32 -l en --project-path ../ --source-dir ./ --doxyfile_dir ./ || true + # copy the generated HTML files to the docs directory for GitHub Pages + mkdir -p ../docs + cp -r _build/en/esp32/html/* ../docs/. + + - name: Build Documentation (PDF) + run: | + cd doc if sh ./build_latex_pdf.sh _build/en/esp32/latex; then echo "PDF_GENERATED=true" >> $GITHUB_ENV else @@ -42,8 +49,6 @@ jobs: rm -f _build/en/esp32/latex/espp_documentation.pdf echo "PDF_GENERATED=false" >> $GITHUB_ENV fi - mkdir -p ../docs - cp -r _build/en/esp32/html/* ../docs/. # warn if the PDF was not generated successfully if [ "$PDF_GENERATED" = "false" ]; then echo "Warning: PDF documentation was not generated successfully." From 3a0aa2b416ccafdc1897bcb0dcda954f74edd7bc Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Fri, 12 Jun 2026 13:49:47 -0500 Subject: [PATCH 04/13] remove some non-ascii characters --- components/cobs/README.md | 8 ++++---- components/cobs/include/cobs.hpp | 3 ++- components/color/include/color.hpp | 12 ++++++------ .../rx8130ce/example/main/rx8130ce_example.cpp | 4 ++-- doc/en/cobs.rst | 2 +- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/components/cobs/README.md b/components/cobs/README.md index 604aec4fe..ab7560bfc 100644 --- a/components/cobs/README.md +++ b/components/cobs/README.md @@ -7,7 +7,7 @@ The COBS component provides efficient encoding and decoding for the Consistent O ## Features - **Zero-byte elimination**: Removes all zero bytes from data, using them as packet delimiters -- **Consistent overhead**: Maximum overhead of ⌈n/254⌉ + 1 bytes per packet +- **Consistent overhead**: Maximum overhead of ceil(n/254) + 1 bytes per packet - **Simple framing**: Uses zero bytes as reliable packet delimiters - **Streaming support**: Handle fragmented data streams and batch multiple packets - **Thread-safe**: Streaming classes are thread-safe with internal locking @@ -170,7 +170,7 @@ decoder.clear(); **Buffer Size Formulas:** -- **`max_encoded_size(payload_len)`**: `payload_len + ⌈payload_len/254⌉ + 2` +- **`max_encoded_size(payload_len)`**: `payload_len + ceil(payload_len/254) + 2` - **`max_decoded_size(encoded_len)`**: `encoded_len - 1` (accounts for delimiter) ## COBS Algorithm Details @@ -179,7 +179,7 @@ COBS works by: 1. **Eliminating zeros**: All zero bytes are removed from the data 2. **Adding overhead bytes**: Each block of non-zero data gets a length prefix 3. **Using zero as delimiter**: A single zero byte marks the end of each packet -4. **Consistent overhead**: Maximum overhead is ⌈n/254⌉ + 1 bytes per packet +4. **Consistent overhead**: Maximum overhead is ceil(n/254) + 1 bytes per packet ### Example Encoding ``` @@ -197,7 +197,7 @@ Output: [0x03, 0x01, 0x02, 0x02, 0x03, 0x04, 0x00] ## Performance Characteristics -- **Encoding overhead**: At most ⌈n/254⌉ + 1 bytes per packet +- **Encoding overhead**: At most ceil(n/254) + 1 bytes per packet - **Decoding complexity**: O(n) where n is packet size - **Speed**: Optimized for embedded systems with minimal overhead - **Large packet support**: Tested and verified with packets up to 1000+ bytes diff --git a/components/cobs/include/cobs.hpp b/components/cobs/include/cobs.hpp index ec28b284b..2d0b59287 100644 --- a/components/cobs/include/cobs.hpp +++ b/components/cobs/include/cobs.hpp @@ -13,7 +13,8 @@ namespace espp { * * Provides single-packet encoding and decoding using the COBS algorithm * with 0 as the delimiter. - * COBS encoding can add at most ⌈n/254⌉ + 1 bytes overhead. Plus 1 byte for the delimiter + * COBS encoding can add at most ceil(n/254) + 1 bytes overhead, plus 1 byte + * for the delimiter. * COBS changes the size of the packet by at least 1 byte, so it's not possible to encode in * place. MAX_BLOCK_SIZE = 254 is the maximum number of non-zero bytes in an encoded block. * diff --git a/components/color/include/color.hpp b/components/color/include/color.hpp index e774a550e..630ef6d88 100644 --- a/components/color/include/color.hpp +++ b/components/color/include/color.hpp @@ -13,9 +13,9 @@ class Hsv; */ class Rgb { public: - float r{0}; ///< Red value ∈ [0, 1] - float g{0}; ///< Green value ∈ [0, 1] - float b{0}; ///< Blue value ∈ [0, 1] + float r{0}; ///< Red value in [0, 1] + float g{0}; ///< Green value in [0, 1] + float b{0}; ///< Blue value in [0, 1] Rgb() = default; @@ -106,9 +106,9 @@ class Rgb { */ class Hsv { public: - float h{0}; ///< Hue ∈ [0, 360] - float s{0}; ///< Saturation ∈ [0, 1] - float v{0}; ///< Value ∈ [0, 1] + float h{0}; ///< Hue in [0, 360] + float s{0}; ///< Saturation in [0, 1] + float v{0}; ///< Value in [0, 1] Hsv() = default; diff --git a/components/rx8130ce/example/main/rx8130ce_example.cpp b/components/rx8130ce/example/main/rx8130ce_example.cpp index 7c994d2c6..f577bd17b 100644 --- a/components/rx8130ce/example/main/rx8130ce_example.cpp +++ b/components/rx8130ce/example/main/rx8130ce_example.cpp @@ -124,13 +124,13 @@ extern "C" void app_main(void) { // Check alarm if (rtc.is_alarm_triggered(ec) && !ec) { - logger.info("🚨 ALARM TRIGGERED!"); + logger.info("ALARM TRIGGERED!"); rtc.clear_alarm_flag(ec); } // Check timer if (rtc.is_timer_expired(ec) && !ec) { - logger.info("⏰ TIMER EXPIRED!"); + logger.info("TIMER EXPIRED!"); rtc.clear_timer_flag(ec); // Restart timer for another 5 seconds diff --git a/doc/en/cobs.rst b/doc/en/cobs.rst index 351eb4ffa..0f16dfe90 100644 --- a/doc/en/cobs.rst +++ b/doc/en/cobs.rst @@ -6,7 +6,7 @@ Overhead Byte Stuffing algorithm, a packet framing protocol that ensures reliabl packet boundaries in communication streams. Key features: -* Zero-byte elimination with consistent overhead (max ⌈n/254⌉ + 1 bytes) +* Zero-byte elimination with consistent overhead (max ceil(n/254) + 1 bytes) * Single packet API for basic encoding/decoding * Streaming API with thread-safe encoder/decoder classes * Support for fragmented data streams and packet batching From 0cbc9bfbb6810fce85d3bae34b426541f8287871 Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Fri, 12 Jun 2026 14:23:16 -0500 Subject: [PATCH 05/13] minor update --- .github/workflows/build_and_publish_docs.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_and_publish_docs.yml b/.github/workflows/build_and_publish_docs.yml index 2c412aef2..bdc343816 100644 --- a/.github/workflows/build_and_publish_docs.yml +++ b/.github/workflows/build_and_publish_docs.yml @@ -44,13 +44,12 @@ jobs: cd doc if sh ./build_latex_pdf.sh _build/en/esp32/latex; then echo "PDF_GENERATED=true" >> $GITHUB_ENV + echo "Success: PDF documentation generated successfully." else rm -f _build/en/esp32/latex/refman.pdf rm -f _build/en/esp32/latex/espp_documentation.pdf echo "PDF_GENERATED=false" >> $GITHUB_ENV - fi - # warn if the PDF was not generated successfully - if [ "$PDF_GENERATED" = "false" ]; then + # warn if the PDF was not generated successfully echo "Warning: PDF documentation was not generated successfully." fi From 37d22d1aabd849b5881eb4cc45b7f023fe4725fe Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Fri, 12 Jun 2026 14:50:02 -0500 Subject: [PATCH 06/13] update examples to remove ascii for testing latex generation --- .../example/main/tabulate_example.cpp | 22 +++++++++---------- .../example/main/thermistor_example.cpp | 2 +- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/components/tabulate/example/main/tabulate_example.cpp b/components/tabulate/example/main/tabulate_example.cpp index e93a3f749..445bfdc21 100644 --- a/components/tabulate/example/main/tabulate_example.cpp +++ b/components/tabulate/example/main/tabulate_example.cpp @@ -21,16 +21,16 @@ extern "C" void app_main(void) { Table universal_constants; universal_constants.add_row({"Quantity", "Value"}); - universal_constants.add_row({"Characteristic impedance of vacuum", "376.730 313 461... Ω"}); + universal_constants.add_row({"Characteristic impedance of vacuum", "376.730 313 461... Ohm"}); universal_constants.add_row( - {"Electric constant (permittivity of free space)", "8.854 187 817... × 10⁻¹²F·m⁻¹"}); + {"Electric constant (permittivity of free space)", "8.854 187 817... x 10^-12 F*m^-1"}); universal_constants.add_row({"Magnetic constant (permeability of free space)", - "4π × 10⁻⁷ N·A⁻² = 1.2566 370 614... × 10⁻⁶ N·A⁻²"}); + "4*pi x 10^-7 N*A^-2 = 1.2566 370 614... x 10^-6 N*A^-2"}); universal_constants.add_row({"Gravitational constant (Newtonian constant of gravitation)", - "6.6742(10) × 10⁻¹¹m³·kg⁻¹·s⁻²"}); - universal_constants.add_row({"Planck's constant", "6.626 0693(11) × 10⁻³⁴ J·s"}); - universal_constants.add_row({"Dirac's constant", "1.054 571 68(18) × 10⁻³⁴ J·s"}); - universal_constants.add_row({"Speed of light in vacuum", "299 792 458 m·s⁻¹"}); + "6.6742(10) x 10^-11 m^3*kg^-1*s^-2"}); + universal_constants.add_row({"Planck's constant", "6.626 0693(11) x 10^-34 J*s"}); + universal_constants.add_row({"Dirac's constant", "1.054 571 68(18) x 10^-34 J*s"}); + universal_constants.add_row({"Speed of light in vacuum", "299 792 458 m*s^-1"}); universal_constants.format() .font_style({FontStyle::bold}) @@ -99,7 +99,7 @@ extern "C" void app_main(void) { Table readme; readme.format().border_color(Color::yellow); - readme.add_row(Row_t{"🔥tabulate for Modern C++🔥"}); + readme.add_row(Row_t{"tabulate for Modern C++"}); readme[0].format().font_align(FontAlign::center).font_color(Color::yellow); readme.add_row(Row_t{"https://github.com/p-ranav/tabulate"}); @@ -182,9 +182,7 @@ extern "C" void app_main(void) { readme[9].format().hide_border_top().border_color(Color::white).font_color(Color::yellow); - readme.add_row(Row_t{"ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ " - "ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ " - "ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ"}); + readme.add_row(Row_t{"Multi-byte sample text rendered in a PDF-friendly ASCII form."}); readme[10] .format() .font_background_color(Color::red) @@ -301,7 +299,7 @@ extern "C" void app_main(void) { chart[8][17].set_text("This one's yellow and right-aligned"); chart[8][17].format().color(Color::yellow).font_align(FontAlign::right); - chart[9][17].set_text("This one's on 🔥🔥🔥"); + chart[9][17].set_text("This one's on fire!"); std::cout << chart; std::cout << legend << "\n\n"; diff --git a/components/thermistor/example/main/thermistor_example.cpp b/components/thermistor/example/main/thermistor_example.cpp index 927299649..55eae69d0 100644 --- a/components/thermistor/example/main/thermistor_example.cpp +++ b/components/thermistor/example/main/thermistor_example.cpp @@ -99,7 +99,7 @@ extern "C" void app_main(void) { // https://product.tdk.com/system/files/dam/doc/product/sensor/ntc/chip-ntc-thermistor/catalog/tpd_commercial_ntc-thermistor_ntcg_en.pdf // From the table (page 7): // clang-format off - // Part Number. | R25(Ω) | Tolerance | B25/50(Κ) | B25/75(Κ) | B25/85(Κ) | B25/100(K) | Current (mA) | Operating Temp Range + // Part Number. | R25(Ohm) | Tolerance | B25/50(K) | B25/75(K) | B25/85(K) | B25/100(K) | Current (mA) | Operating Temp Range // NTCG103JF103FT1 | 10,000 | +/–1% | 3380 | 3422 | 3435 | 3453 +/–1% | 0.31 | –40 to 152 // clang-format on espp::Thermistor thermistor({.divider_config = espp::Thermistor::ResistorDividerConfig::UPPER, From f7fcafbe2a805ad1172b7741a1f16d16efccfb6c Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Fri, 12 Jun 2026 15:52:51 -0500 Subject: [PATCH 07/13] fix ci --- .github/workflows/build_and_publish_docs.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_and_publish_docs.yml b/.github/workflows/build_and_publish_docs.yml index bdc343816..3b9ba94b8 100644 --- a/.github/workflows/build_and_publish_docs.yml +++ b/.github/workflows/build_and_publish_docs.yml @@ -37,17 +37,17 @@ jobs: build-docs -bs html -t esp32 -l en --project-path ../ --source-dir ./ --doxyfile_dir ./ || true # copy the generated HTML files to the docs directory for GitHub Pages mkdir -p ../docs - cp -r _build/en/esp32/html/* ../docs/. + cp -r ../_build/en/esp32/html/* ../docs/. - name: Build Documentation (PDF) run: | cd doc - if sh ./build_latex_pdf.sh _build/en/esp32/latex; then + if sh ./build_latex_pdf.sh ../_build/en/esp32/latex; then echo "PDF_GENERATED=true" >> $GITHUB_ENV echo "Success: PDF documentation generated successfully." else - rm -f _build/en/esp32/latex/refman.pdf - rm -f _build/en/esp32/latex/espp_documentation.pdf + rm -f ../_build/en/esp32/latex/refman.pdf + rm -f ../_build/en/esp32/latex/espp_documentation.pdf echo "PDF_GENERATED=false" >> $GITHUB_ENV # warn if the PDF was not generated successfully echo "Warning: PDF documentation was not generated successfully." @@ -64,11 +64,11 @@ jobs: if: env.PDF_GENERATED == 'true' with: name: espp_documentation.pdf - path: doc/_build/en/esp32/latex/espp_documentation.pdf + path: _build/en/esp32/latex/espp_documentation.pdf - name: Attach files to release uses: softprops/action-gh-release@v2 if: ${{ github.event.release && github.event.action == 'published' && env.PDF_GENERATED == 'true' }} with: files: | - doc/_build/en/esp32/latex/espp_documentation.pdf + _build/en/esp32/latex/espp_documentation.pdf From 15c5154aaf7786fcb49bc3c0d9c4a7182791eb2b Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Fri, 12 Jun 2026 16:09:43 -0500 Subject: [PATCH 08/13] try to clean up and make it less brittle --- .github/workflows/build_and_publish_docs.yml | 24 +++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_and_publish_docs.yml b/.github/workflows/build_and_publish_docs.yml index 3b9ba94b8..3df9e1c68 100644 --- a/.github/workflows/build_and_publish_docs.yml +++ b/.github/workflows/build_and_publish_docs.yml @@ -35,19 +35,31 @@ jobs: cd doc # ignore if the following command fails build-docs -bs html -t esp32 -l en --project-path ../ --source-dir ./ --doxyfile_dir ./ || true + if [ -d _build/en/esp32/html ]; then + build_dir_from_doc=_build/en/esp32 + build_dir_root=doc/_build/en/esp32 + elif [ -d ../_build/en/esp32/html ]; then + build_dir_from_doc=../_build/en/esp32 + build_dir_root=_build/en/esp32 + else + echo "Unable to find generated documentation output directory." >&2 + exit 1 + fi + echo "DOC_BUILD_DIR_FROM_DOC=${build_dir_from_doc}" >> $GITHUB_ENV + echo "DOC_BUILD_DIR_ROOT=${build_dir_root}" >> $GITHUB_ENV # copy the generated HTML files to the docs directory for GitHub Pages mkdir -p ../docs - cp -r ../_build/en/esp32/html/* ../docs/. + cp -r "${build_dir_from_doc}/html/"* ../docs/. - name: Build Documentation (PDF) run: | cd doc - if sh ./build_latex_pdf.sh ../_build/en/esp32/latex; then + if sh ./build_latex_pdf.sh "${DOC_BUILD_DIR_FROM_DOC}/latex"; then echo "PDF_GENERATED=true" >> $GITHUB_ENV echo "Success: PDF documentation generated successfully." else - rm -f ../_build/en/esp32/latex/refman.pdf - rm -f ../_build/en/esp32/latex/espp_documentation.pdf + rm -f "${DOC_BUILD_DIR_FROM_DOC}/latex/refman.pdf" + rm -f "${DOC_BUILD_DIR_FROM_DOC}/latex/espp_documentation.pdf" echo "PDF_GENERATED=false" >> $GITHUB_ENV # warn if the PDF was not generated successfully echo "Warning: PDF documentation was not generated successfully." @@ -64,11 +76,11 @@ jobs: if: env.PDF_GENERATED == 'true' with: name: espp_documentation.pdf - path: _build/en/esp32/latex/espp_documentation.pdf + path: ${{ env.DOC_BUILD_DIR_ROOT }}/latex/espp_documentation.pdf - name: Attach files to release uses: softprops/action-gh-release@v2 if: ${{ github.event.release && github.event.action == 'published' && env.PDF_GENERATED == 'true' }} with: files: | - _build/en/esp32/latex/espp_documentation.pdf + ${{ env.DOC_BUILD_DIR_ROOT }}/latex/espp_documentation.pdf From 546c429986ac61666cdfa8e250c2b25d5399a76e Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Fri, 12 Jun 2026 16:36:44 -0500 Subject: [PATCH 09/13] fix script --- doc/build_latex_pdf.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/build_latex_pdf.sh b/doc/build_latex_pdf.sh index 4c578e0e3..f842f1f01 100755 --- a/doc/build_latex_pdf.sh +++ b/doc/build_latex_pdf.sh @@ -11,6 +11,9 @@ if [ ! -d "$latex_dir" ]; then echo "latex directory not found: $latex_dir" >&2 exit 1 fi +latex_dir=$( + CDPATH= cd -- "$latex_dir" && pwd +) script_dir=$( CDPATH= cd -- "$(dirname -- "$0")" && pwd From 6d6cdadc48075d6a9dd53edeceecc48a5cc8296a Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Fri, 12 Jun 2026 16:52:26 -0500 Subject: [PATCH 10/13] Potential fix for pull request finding 'Unused local variable' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> --- doc/patch_doxygen_latex.py | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/patch_doxygen_latex.py b/doc/patch_doxygen_latex.py index 5fc237114..43f9b7837 100644 --- a/doc/patch_doxygen_latex.py +++ b/doc/patch_doxygen_latex.py @@ -86,7 +86,6 @@ def main() -> int: text = style_path.read_text() if NEW_NEWDOCUMENT_BLOCK in text or NEW_NEWENV_BLOCK in text: - replacements = 0 updated_text = text else: updated_text, replacements = OLD_NEWDOCUMENT_PATTERN.subn( From 9fb9ca9a1745b70ecd0655f6577b6789953a029b Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Fri, 12 Jun 2026 16:54:28 -0500 Subject: [PATCH 11/13] revert code changes to test build --- components/cobs/README.md | 8 +++---- components/cobs/include/cobs.hpp | 3 +-- components/color/include/color.hpp | 12 +++++----- .../example/main/rx8130ce_example.cpp | 4 ++-- .../example/main/tabulate_example.cpp | 22 ++++++++++--------- .../example/main/thermistor_example.cpp | 2 +- 6 files changed, 26 insertions(+), 25 deletions(-) diff --git a/components/cobs/README.md b/components/cobs/README.md index ab7560bfc..604aec4fe 100644 --- a/components/cobs/README.md +++ b/components/cobs/README.md @@ -7,7 +7,7 @@ The COBS component provides efficient encoding and decoding for the Consistent O ## Features - **Zero-byte elimination**: Removes all zero bytes from data, using them as packet delimiters -- **Consistent overhead**: Maximum overhead of ceil(n/254) + 1 bytes per packet +- **Consistent overhead**: Maximum overhead of ⌈n/254⌉ + 1 bytes per packet - **Simple framing**: Uses zero bytes as reliable packet delimiters - **Streaming support**: Handle fragmented data streams and batch multiple packets - **Thread-safe**: Streaming classes are thread-safe with internal locking @@ -170,7 +170,7 @@ decoder.clear(); **Buffer Size Formulas:** -- **`max_encoded_size(payload_len)`**: `payload_len + ceil(payload_len/254) + 2` +- **`max_encoded_size(payload_len)`**: `payload_len + ⌈payload_len/254⌉ + 2` - **`max_decoded_size(encoded_len)`**: `encoded_len - 1` (accounts for delimiter) ## COBS Algorithm Details @@ -179,7 +179,7 @@ COBS works by: 1. **Eliminating zeros**: All zero bytes are removed from the data 2. **Adding overhead bytes**: Each block of non-zero data gets a length prefix 3. **Using zero as delimiter**: A single zero byte marks the end of each packet -4. **Consistent overhead**: Maximum overhead is ceil(n/254) + 1 bytes per packet +4. **Consistent overhead**: Maximum overhead is ⌈n/254⌉ + 1 bytes per packet ### Example Encoding ``` @@ -197,7 +197,7 @@ Output: [0x03, 0x01, 0x02, 0x02, 0x03, 0x04, 0x00] ## Performance Characteristics -- **Encoding overhead**: At most ceil(n/254) + 1 bytes per packet +- **Encoding overhead**: At most ⌈n/254⌉ + 1 bytes per packet - **Decoding complexity**: O(n) where n is packet size - **Speed**: Optimized for embedded systems with minimal overhead - **Large packet support**: Tested and verified with packets up to 1000+ bytes diff --git a/components/cobs/include/cobs.hpp b/components/cobs/include/cobs.hpp index 2d0b59287..ec28b284b 100644 --- a/components/cobs/include/cobs.hpp +++ b/components/cobs/include/cobs.hpp @@ -13,8 +13,7 @@ namespace espp { * * Provides single-packet encoding and decoding using the COBS algorithm * with 0 as the delimiter. - * COBS encoding can add at most ceil(n/254) + 1 bytes overhead, plus 1 byte - * for the delimiter. + * COBS encoding can add at most ⌈n/254⌉ + 1 bytes overhead. Plus 1 byte for the delimiter * COBS changes the size of the packet by at least 1 byte, so it's not possible to encode in * place. MAX_BLOCK_SIZE = 254 is the maximum number of non-zero bytes in an encoded block. * diff --git a/components/color/include/color.hpp b/components/color/include/color.hpp index 630ef6d88..e774a550e 100644 --- a/components/color/include/color.hpp +++ b/components/color/include/color.hpp @@ -13,9 +13,9 @@ class Hsv; */ class Rgb { public: - float r{0}; ///< Red value in [0, 1] - float g{0}; ///< Green value in [0, 1] - float b{0}; ///< Blue value in [0, 1] + float r{0}; ///< Red value ∈ [0, 1] + float g{0}; ///< Green value ∈ [0, 1] + float b{0}; ///< Blue value ∈ [0, 1] Rgb() = default; @@ -106,9 +106,9 @@ class Rgb { */ class Hsv { public: - float h{0}; ///< Hue in [0, 360] - float s{0}; ///< Saturation in [0, 1] - float v{0}; ///< Value in [0, 1] + float h{0}; ///< Hue ∈ [0, 360] + float s{0}; ///< Saturation ∈ [0, 1] + float v{0}; ///< Value ∈ [0, 1] Hsv() = default; diff --git a/components/rx8130ce/example/main/rx8130ce_example.cpp b/components/rx8130ce/example/main/rx8130ce_example.cpp index f577bd17b..7c994d2c6 100644 --- a/components/rx8130ce/example/main/rx8130ce_example.cpp +++ b/components/rx8130ce/example/main/rx8130ce_example.cpp @@ -124,13 +124,13 @@ extern "C" void app_main(void) { // Check alarm if (rtc.is_alarm_triggered(ec) && !ec) { - logger.info("ALARM TRIGGERED!"); + logger.info("🚨 ALARM TRIGGERED!"); rtc.clear_alarm_flag(ec); } // Check timer if (rtc.is_timer_expired(ec) && !ec) { - logger.info("TIMER EXPIRED!"); + logger.info("⏰ TIMER EXPIRED!"); rtc.clear_timer_flag(ec); // Restart timer for another 5 seconds diff --git a/components/tabulate/example/main/tabulate_example.cpp b/components/tabulate/example/main/tabulate_example.cpp index 445bfdc21..e93a3f749 100644 --- a/components/tabulate/example/main/tabulate_example.cpp +++ b/components/tabulate/example/main/tabulate_example.cpp @@ -21,16 +21,16 @@ extern "C" void app_main(void) { Table universal_constants; universal_constants.add_row({"Quantity", "Value"}); - universal_constants.add_row({"Characteristic impedance of vacuum", "376.730 313 461... Ohm"}); + universal_constants.add_row({"Characteristic impedance of vacuum", "376.730 313 461... Ω"}); universal_constants.add_row( - {"Electric constant (permittivity of free space)", "8.854 187 817... x 10^-12 F*m^-1"}); + {"Electric constant (permittivity of free space)", "8.854 187 817... × 10⁻¹²F·m⁻¹"}); universal_constants.add_row({"Magnetic constant (permeability of free space)", - "4*pi x 10^-7 N*A^-2 = 1.2566 370 614... x 10^-6 N*A^-2"}); + "4π × 10⁻⁷ N·A⁻² = 1.2566 370 614... × 10⁻⁶ N·A⁻²"}); universal_constants.add_row({"Gravitational constant (Newtonian constant of gravitation)", - "6.6742(10) x 10^-11 m^3*kg^-1*s^-2"}); - universal_constants.add_row({"Planck's constant", "6.626 0693(11) x 10^-34 J*s"}); - universal_constants.add_row({"Dirac's constant", "1.054 571 68(18) x 10^-34 J*s"}); - universal_constants.add_row({"Speed of light in vacuum", "299 792 458 m*s^-1"}); + "6.6742(10) × 10⁻¹¹m³·kg⁻¹·s⁻²"}); + universal_constants.add_row({"Planck's constant", "6.626 0693(11) × 10⁻³⁴ J·s"}); + universal_constants.add_row({"Dirac's constant", "1.054 571 68(18) × 10⁻³⁴ J·s"}); + universal_constants.add_row({"Speed of light in vacuum", "299 792 458 m·s⁻¹"}); universal_constants.format() .font_style({FontStyle::bold}) @@ -99,7 +99,7 @@ extern "C" void app_main(void) { Table readme; readme.format().border_color(Color::yellow); - readme.add_row(Row_t{"tabulate for Modern C++"}); + readme.add_row(Row_t{"🔥tabulate for Modern C++🔥"}); readme[0].format().font_align(FontAlign::center).font_color(Color::yellow); readme.add_row(Row_t{"https://github.com/p-ranav/tabulate"}); @@ -182,7 +182,9 @@ extern "C" void app_main(void) { readme[9].format().hide_border_top().border_color(Color::white).font_color(Color::yellow); - readme.add_row(Row_t{"Multi-byte sample text rendered in a PDF-friendly ASCII form."}); + readme.add_row(Row_t{"ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ " + "ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ " + "ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ"}); readme[10] .format() .font_background_color(Color::red) @@ -299,7 +301,7 @@ extern "C" void app_main(void) { chart[8][17].set_text("This one's yellow and right-aligned"); chart[8][17].format().color(Color::yellow).font_align(FontAlign::right); - chart[9][17].set_text("This one's on fire!"); + chart[9][17].set_text("This one's on 🔥🔥🔥"); std::cout << chart; std::cout << legend << "\n\n"; diff --git a/components/thermistor/example/main/thermistor_example.cpp b/components/thermistor/example/main/thermistor_example.cpp index 55eae69d0..927299649 100644 --- a/components/thermistor/example/main/thermistor_example.cpp +++ b/components/thermistor/example/main/thermistor_example.cpp @@ -99,7 +99,7 @@ extern "C" void app_main(void) { // https://product.tdk.com/system/files/dam/doc/product/sensor/ntc/chip-ntc-thermistor/catalog/tpd_commercial_ntc-thermistor_ntcg_en.pdf // From the table (page 7): // clang-format off - // Part Number. | R25(Ohm) | Tolerance | B25/50(K) | B25/75(K) | B25/85(K) | B25/100(K) | Current (mA) | Operating Temp Range + // Part Number. | R25(Ω) | Tolerance | B25/50(Κ) | B25/75(Κ) | B25/85(Κ) | B25/100(K) | Current (mA) | Operating Temp Range // NTCG103JF103FT1 | 10,000 | +/–1% | 3380 | 3422 | 3435 | 3453 +/–1% | 0.31 | –40 to 152 // clang-format on espp::Thermistor thermistor({.divider_config = espp::Thermistor::ResistorDividerConfig::UPPER, From 480d8359f32e704c14eba202bf8295c0a81b8b7d Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Sat, 13 Jun 2026 15:09:38 -0500 Subject: [PATCH 12/13] update to latest upload artifact --- .github/workflows/build_and_publish_docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_and_publish_docs.yml b/.github/workflows/build_and_publish_docs.yml index 3df9e1c68..c7a4e9377 100644 --- a/.github/workflows/build_and_publish_docs.yml +++ b/.github/workflows/build_and_publish_docs.yml @@ -72,7 +72,7 @@ jobs: publish_dir: ./docs force_orphan: true - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v5 if: env.PDF_GENERATED == 'true' with: name: espp_documentation.pdf From d87edc4f781608178af12685ae3ececf7ee4a1ce Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Sat, 13 Jun 2026 15:12:49 -0500 Subject: [PATCH 13/13] Revert "revert code changes to test build" This reverts commit 9fb9ca9a1745b70ecd0655f6577b6789953a029b. --- components/cobs/README.md | 8 +++---- components/cobs/include/cobs.hpp | 3 ++- components/color/include/color.hpp | 12 +++++----- .../example/main/rx8130ce_example.cpp | 4 ++-- .../example/main/tabulate_example.cpp | 22 +++++++++---------- .../example/main/thermistor_example.cpp | 2 +- 6 files changed, 25 insertions(+), 26 deletions(-) diff --git a/components/cobs/README.md b/components/cobs/README.md index 604aec4fe..ab7560bfc 100644 --- a/components/cobs/README.md +++ b/components/cobs/README.md @@ -7,7 +7,7 @@ The COBS component provides efficient encoding and decoding for the Consistent O ## Features - **Zero-byte elimination**: Removes all zero bytes from data, using them as packet delimiters -- **Consistent overhead**: Maximum overhead of ⌈n/254⌉ + 1 bytes per packet +- **Consistent overhead**: Maximum overhead of ceil(n/254) + 1 bytes per packet - **Simple framing**: Uses zero bytes as reliable packet delimiters - **Streaming support**: Handle fragmented data streams and batch multiple packets - **Thread-safe**: Streaming classes are thread-safe with internal locking @@ -170,7 +170,7 @@ decoder.clear(); **Buffer Size Formulas:** -- **`max_encoded_size(payload_len)`**: `payload_len + ⌈payload_len/254⌉ + 2` +- **`max_encoded_size(payload_len)`**: `payload_len + ceil(payload_len/254) + 2` - **`max_decoded_size(encoded_len)`**: `encoded_len - 1` (accounts for delimiter) ## COBS Algorithm Details @@ -179,7 +179,7 @@ COBS works by: 1. **Eliminating zeros**: All zero bytes are removed from the data 2. **Adding overhead bytes**: Each block of non-zero data gets a length prefix 3. **Using zero as delimiter**: A single zero byte marks the end of each packet -4. **Consistent overhead**: Maximum overhead is ⌈n/254⌉ + 1 bytes per packet +4. **Consistent overhead**: Maximum overhead is ceil(n/254) + 1 bytes per packet ### Example Encoding ``` @@ -197,7 +197,7 @@ Output: [0x03, 0x01, 0x02, 0x02, 0x03, 0x04, 0x00] ## Performance Characteristics -- **Encoding overhead**: At most ⌈n/254⌉ + 1 bytes per packet +- **Encoding overhead**: At most ceil(n/254) + 1 bytes per packet - **Decoding complexity**: O(n) where n is packet size - **Speed**: Optimized for embedded systems with minimal overhead - **Large packet support**: Tested and verified with packets up to 1000+ bytes diff --git a/components/cobs/include/cobs.hpp b/components/cobs/include/cobs.hpp index ec28b284b..2d0b59287 100644 --- a/components/cobs/include/cobs.hpp +++ b/components/cobs/include/cobs.hpp @@ -13,7 +13,8 @@ namespace espp { * * Provides single-packet encoding and decoding using the COBS algorithm * with 0 as the delimiter. - * COBS encoding can add at most ⌈n/254⌉ + 1 bytes overhead. Plus 1 byte for the delimiter + * COBS encoding can add at most ceil(n/254) + 1 bytes overhead, plus 1 byte + * for the delimiter. * COBS changes the size of the packet by at least 1 byte, so it's not possible to encode in * place. MAX_BLOCK_SIZE = 254 is the maximum number of non-zero bytes in an encoded block. * diff --git a/components/color/include/color.hpp b/components/color/include/color.hpp index e774a550e..630ef6d88 100644 --- a/components/color/include/color.hpp +++ b/components/color/include/color.hpp @@ -13,9 +13,9 @@ class Hsv; */ class Rgb { public: - float r{0}; ///< Red value ∈ [0, 1] - float g{0}; ///< Green value ∈ [0, 1] - float b{0}; ///< Blue value ∈ [0, 1] + float r{0}; ///< Red value in [0, 1] + float g{0}; ///< Green value in [0, 1] + float b{0}; ///< Blue value in [0, 1] Rgb() = default; @@ -106,9 +106,9 @@ class Rgb { */ class Hsv { public: - float h{0}; ///< Hue ∈ [0, 360] - float s{0}; ///< Saturation ∈ [0, 1] - float v{0}; ///< Value ∈ [0, 1] + float h{0}; ///< Hue in [0, 360] + float s{0}; ///< Saturation in [0, 1] + float v{0}; ///< Value in [0, 1] Hsv() = default; diff --git a/components/rx8130ce/example/main/rx8130ce_example.cpp b/components/rx8130ce/example/main/rx8130ce_example.cpp index 7c994d2c6..f577bd17b 100644 --- a/components/rx8130ce/example/main/rx8130ce_example.cpp +++ b/components/rx8130ce/example/main/rx8130ce_example.cpp @@ -124,13 +124,13 @@ extern "C" void app_main(void) { // Check alarm if (rtc.is_alarm_triggered(ec) && !ec) { - logger.info("🚨 ALARM TRIGGERED!"); + logger.info("ALARM TRIGGERED!"); rtc.clear_alarm_flag(ec); } // Check timer if (rtc.is_timer_expired(ec) && !ec) { - logger.info("⏰ TIMER EXPIRED!"); + logger.info("TIMER EXPIRED!"); rtc.clear_timer_flag(ec); // Restart timer for another 5 seconds diff --git a/components/tabulate/example/main/tabulate_example.cpp b/components/tabulate/example/main/tabulate_example.cpp index e93a3f749..445bfdc21 100644 --- a/components/tabulate/example/main/tabulate_example.cpp +++ b/components/tabulate/example/main/tabulate_example.cpp @@ -21,16 +21,16 @@ extern "C" void app_main(void) { Table universal_constants; universal_constants.add_row({"Quantity", "Value"}); - universal_constants.add_row({"Characteristic impedance of vacuum", "376.730 313 461... Ω"}); + universal_constants.add_row({"Characteristic impedance of vacuum", "376.730 313 461... Ohm"}); universal_constants.add_row( - {"Electric constant (permittivity of free space)", "8.854 187 817... × 10⁻¹²F·m⁻¹"}); + {"Electric constant (permittivity of free space)", "8.854 187 817... x 10^-12 F*m^-1"}); universal_constants.add_row({"Magnetic constant (permeability of free space)", - "4π × 10⁻⁷ N·A⁻² = 1.2566 370 614... × 10⁻⁶ N·A⁻²"}); + "4*pi x 10^-7 N*A^-2 = 1.2566 370 614... x 10^-6 N*A^-2"}); universal_constants.add_row({"Gravitational constant (Newtonian constant of gravitation)", - "6.6742(10) × 10⁻¹¹m³·kg⁻¹·s⁻²"}); - universal_constants.add_row({"Planck's constant", "6.626 0693(11) × 10⁻³⁴ J·s"}); - universal_constants.add_row({"Dirac's constant", "1.054 571 68(18) × 10⁻³⁴ J·s"}); - universal_constants.add_row({"Speed of light in vacuum", "299 792 458 m·s⁻¹"}); + "6.6742(10) x 10^-11 m^3*kg^-1*s^-2"}); + universal_constants.add_row({"Planck's constant", "6.626 0693(11) x 10^-34 J*s"}); + universal_constants.add_row({"Dirac's constant", "1.054 571 68(18) x 10^-34 J*s"}); + universal_constants.add_row({"Speed of light in vacuum", "299 792 458 m*s^-1"}); universal_constants.format() .font_style({FontStyle::bold}) @@ -99,7 +99,7 @@ extern "C" void app_main(void) { Table readme; readme.format().border_color(Color::yellow); - readme.add_row(Row_t{"🔥tabulate for Modern C++🔥"}); + readme.add_row(Row_t{"tabulate for Modern C++"}); readme[0].format().font_align(FontAlign::center).font_color(Color::yellow); readme.add_row(Row_t{"https://github.com/p-ranav/tabulate"}); @@ -182,9 +182,7 @@ extern "C" void app_main(void) { readme[9].format().hide_border_top().border_color(Color::white).font_color(Color::yellow); - readme.add_row(Row_t{"ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ " - "ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ " - "ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ"}); + readme.add_row(Row_t{"Multi-byte sample text rendered in a PDF-friendly ASCII form."}); readme[10] .format() .font_background_color(Color::red) @@ -301,7 +299,7 @@ extern "C" void app_main(void) { chart[8][17].set_text("This one's yellow and right-aligned"); chart[8][17].format().color(Color::yellow).font_align(FontAlign::right); - chart[9][17].set_text("This one's on 🔥🔥🔥"); + chart[9][17].set_text("This one's on fire!"); std::cout << chart; std::cout << legend << "\n\n"; diff --git a/components/thermistor/example/main/thermistor_example.cpp b/components/thermistor/example/main/thermistor_example.cpp index 927299649..55eae69d0 100644 --- a/components/thermistor/example/main/thermistor_example.cpp +++ b/components/thermistor/example/main/thermistor_example.cpp @@ -99,7 +99,7 @@ extern "C" void app_main(void) { // https://product.tdk.com/system/files/dam/doc/product/sensor/ntc/chip-ntc-thermistor/catalog/tpd_commercial_ntc-thermistor_ntcg_en.pdf // From the table (page 7): // clang-format off - // Part Number. | R25(Ω) | Tolerance | B25/50(Κ) | B25/75(Κ) | B25/85(Κ) | B25/100(K) | Current (mA) | Operating Temp Range + // Part Number. | R25(Ohm) | Tolerance | B25/50(K) | B25/75(K) | B25/85(K) | B25/100(K) | Current (mA) | Operating Temp Range // NTCG103JF103FT1 | 10,000 | +/–1% | 3380 | 3422 | 3435 | 3453 +/–1% | 0.31 | –40 to 152 // clang-format on espp::Thermistor thermistor({.divider_config = espp::Thermistor::ResistorDividerConfig::UPPER,