diff --git a/.github/workflows/build_and_publish_docs.yml b/.github/workflows/build_and_publish_docs.yml index 0c200fb38..461f7b827 100644 --- a/.github/workflows/build_and_publish_docs.yml +++ b/.github/workflows/build_and_publish_docs.yml @@ -39,12 +39,24 @@ jobs: cp -r _build/en/esp32/html/* ../docs/. # go to the latex output cd _build/en/esp32/latex/ - # build once (ignore if command fails) - pdflatex -interaction=batchmode refman || true + # use xelatex because the generated docs include Unicode characters + # that pdflatex cannot render reliably + xelatex -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 - # rename refman to espp_documentation.pdf - mv refman.pdf espp_documentation.pdf + xelatex -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 + echo "PDF_GENERATED=true" >> $GITHUB_ENV + else + echo "PDF_GENERATED=false" >> $GITHUB_ENV + fi + # warn if the PDF was not generated successfully + if [ "$PDF_GENERATED" = "false" ]; then + echo "Warning: PDF documentation was not generated successfully." + fi - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v4 @@ -54,13 +66,14 @@ jobs: force_orphan: true - uses: actions/upload-artifact@v4 + if: env.PDF_GENERATED == 'true' with: name: espp_documentation.pdf path: doc/_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' }} + if: ${{ github.event.release && github.event.action == 'published' && env.PDF_GENERATED == 'true' }} with: files: | doc/_build/en/esp32/latex/espp_documentation.pdf diff --git a/components/dns_server/example/main/dns_server_example.cpp b/components/dns_server/example/main/dns_server_example.cpp index 00430258a..adf69157b 100644 --- a/components/dns_server/example/main/dns_server_example.cpp +++ b/components/dns_server/example/main/dns_server_example.cpp @@ -9,6 +9,7 @@ using namespace std::chrono_literals; extern "C" void app_main(void) { + //! [dns server example] espp::Logger logger({.tag = "DNS Server Example", .level = espp::Logger::Verbosity::INFO}); logger.info("Starting DNS Server Example"); @@ -58,4 +59,5 @@ extern "C" void app_main(void) { while (true) { std::this_thread::sleep_for(1s); } + //! [dns server example] } diff --git a/components/i2c/include/i2c_master_device_menu.hpp b/components/i2c/include/i2c_master_device_menu.hpp index 4877647c1..71358fd4f 100644 --- a/components/i2c/include/i2c_master_device_menu.hpp +++ b/components/i2c/include/i2c_master_device_menu.hpp @@ -86,6 +86,7 @@ template class I2cMasterDeviceMenu { protected: /// @brief Set the log level for the I2c device. /// @param out The output stream to write to. + /// @param device The I2C master device whose log level will be updated. /// @param verbosity The verbosity level to set. static void set_log_level(std::ostream &out, const std::shared_ptr> &device, @@ -113,6 +114,7 @@ template class I2cMasterDeviceMenu { /// @brief Probe for the device on the bus. /// @param out The output stream to write to. + /// @param device The I2C master device to probe. static void probe_device(std::ostream &out, const std::shared_ptr> &device) { if (!device) { @@ -129,6 +131,7 @@ template class I2cMasterDeviceMenu { /// @brief Read from a register. /// @param out The output stream to write to. + /// @param device The I2C master device to read from. /// @param reg The register to read from. /// @param len The number of bytes to read. static void read_register(std::ostream &out, @@ -150,6 +153,7 @@ template class I2cMasterDeviceMenu { /// @brief Write to a register. /// @param out The output stream to write to. + /// @param device The I2C master device to write to. /// @param reg The register to write to. /// @param data The data to write. static void write_register(std::ostream &out, diff --git a/components/i2c/include/i2c_master_menu.hpp b/components/i2c/include/i2c_master_menu.hpp index 414894d98..0eef2754e 100644 --- a/components/i2c/include/i2c_master_menu.hpp +++ b/components/i2c/include/i2c_master_menu.hpp @@ -95,6 +95,7 @@ class I2cMasterMenu { protected: /// @brief Set the log level for the I2c master bus. /// @param out The output stream to write to. + /// @param bus The I2C master bus whose log level will be updated. /// @param verbosity The verbosity level to set. static void set_log_level(std::ostream &out, espp::I2cMasterBus &bus, const std::string &verbosity) { @@ -117,6 +118,7 @@ class I2cMasterMenu { /// @brief Scan the I2c master bus for devices. /// @param out The output stream to write to. + /// @param bus The I2C master bus to scan. static void scan_bus(std::ostream &out, espp::I2cMasterBus &bus) { out << "Scanning I2c master bus. This may take a while.\n"; auto prev_log_level = bus.get_log_level(); @@ -140,6 +142,7 @@ class I2cMasterMenu { /// @brief Probe for a device at a specific address. /// @param out The output stream to write to. + /// @param bus The I2C master bus to probe on. /// @param address The address to probe for. static void probe_device(std::ostream &out, espp::I2cMasterBus &bus, uint16_t address) { std::error_code ec; @@ -152,6 +155,7 @@ class I2cMasterMenu { /// @brief Read from a device at a specific address and register. /// @param out The output stream to write to. + /// @param bus The I2C master bus used to create the temporary device handle. /// @param address The address to read from. /// @param reg The register to read from. /// @param len The number of bytes to read. @@ -177,6 +181,7 @@ class I2cMasterMenu { /// @brief Write to a device at a specific address and register. /// @param out The output stream to write to. + /// @param bus The I2C master bus used to create the temporary device handle. /// @param address The address to write to. /// @param data The data to write (first byte is register, rest is data). static void write_device(std::ostream &out, diff --git a/components/m5stack-tab5/include/m5stack-tab5.hpp b/components/m5stack-tab5/include/m5stack-tab5.hpp index 6705e8bc3..581e7c861 100644 --- a/components/m5stack-tab5/include/m5stack-tab5.hpp +++ b/components/m5stack-tab5/include/m5stack-tab5.hpp @@ -419,12 +419,12 @@ class M5StackTab5 : public BaseComponent { bool initialize_io_expanders(); /// Control the LCD reset (active-low) routed via IO expander (0x43 P4) - /// \param assert_reset=true drives reset low; false releases reset high. + /// \param assert_reset True drives reset low; false releases reset high. /// \return true on success bool lcd_reset(bool assert_reset); /// Control the GT911 touch reset (active-low) via IO expander (0x43 P5) - /// \param assert_reset=true drives reset low; false releases reset high. + /// \param assert_reset True drives reset low; false releases reset high. /// \return true on success bool touch_reset(bool assert_reset); diff --git a/components/motorgo-plink/example/main/motorgo_plink_example.cpp b/components/motorgo-plink/example/main/motorgo_plink_example.cpp index be63101c2..cb47edb7f 100644 --- a/components/motorgo-plink/example/main/motorgo_plink_example.cpp +++ b/components/motorgo-plink/example/main/motorgo_plink_example.cpp @@ -132,6 +132,7 @@ void log_motor_outputs(espp::MotorGoPlink &board) { } // namespace extern "C" void app_main() { + //! [motorgo-plink example] auto &board = espp::MotorGoPlink::get(); if (!board.initialize_leds()) { @@ -191,6 +192,8 @@ extern "C" void app_main() { log_imu_data(board); - vTaskDelay(pdMS_TO_TICKS(500)); + using namespace std::chrono_literals; + std::this_thread::sleep_for(500ms); } + //! [motorgo-plink example] } diff --git a/components/rtsp/include/generic_depacketizer.hpp b/components/rtsp/include/generic_depacketizer.hpp index c2cdc8126..60328a203 100644 --- a/components/rtsp/include/generic_depacketizer.hpp +++ b/components/rtsp/include/generic_depacketizer.hpp @@ -17,7 +17,7 @@ namespace espp { /// format that uses simple marker-based framing. /// /// \section generic_depacketizer_ex1 Example -/// \snippet generic_depacketizer_example.cpp generic_depacketizer example +/// \snippet rtsp_example.cpp generic_depacketizer_test class GenericDepacketizer : public RtpDepacketizer { public: /// Configuration for GenericDepacketizer. diff --git a/components/rtsp/include/generic_packetizer.hpp b/components/rtsp/include/generic_packetizer.hpp index 1ba7cee7e..ad7512ee2 100644 --- a/components/rtsp/include/generic_packetizer.hpp +++ b/components/rtsp/include/generic_packetizer.hpp @@ -13,7 +13,7 @@ namespace espp { /// chunk with the RTP marker bit. /// /// \section generic_packetizer_ex1 Example -/// \snippet generic_packetizer_example.cpp generic_packetizer example +/// \snippet rtsp_example.cpp generic_packetizer_test class GenericPacketizer : public RtpPacketizer { public: /// Configuration for GenericPacketizer. diff --git a/components/rtsp/include/h264_depacketizer.hpp b/components/rtsp/include/h264_depacketizer.hpp index 6fc553adf..ea30ad2a3 100755 --- a/components/rtsp/include/h264_depacketizer.hpp +++ b/components/rtsp/include/h264_depacketizer.hpp @@ -22,7 +22,7 @@ namespace espp { /// via the frame callback set with set_frame_callback(). /// /// \section h264_depacketizer_ex1 Example -/// \snippet h264_depacketizer_example.cpp h264_depacketizer example +/// \snippet rtsp_example.cpp h264_depacketizer_test class H264Depacketizer : public RtpDepacketizer { public: /// Configuration for the H264Depacketizer. diff --git a/components/rtsp/include/h264_packetizer.hpp b/components/rtsp/include/h264_packetizer.hpp index 5d277b04d..569a22fb5 100644 --- a/components/rtsp/include/h264_packetizer.hpp +++ b/components/rtsp/include/h264_packetizer.hpp @@ -23,7 +23,7 @@ namespace espp { /// SSRC). The caller wraps each returned chunk into an RtpPacket. /// /// \section h264_packetizer_ex1 Example -/// \snippet h264_packetizer_example.cpp h264_packetizer example +/// \snippet rtsp_example.cpp h264_packetizer_test class H264Packetizer : public RtpPacketizer { public: /// Configuration for the H264Packetizer. diff --git a/components/spi/include/spi.hpp b/components/spi/include/spi.hpp index 0db5eed67..0caa97e00 100644 --- a/components/spi/include/spi.hpp +++ b/components/spi/include/spi.hpp @@ -121,13 +121,13 @@ class Spi : public BaseComponent { Spi(Spi &&) = delete; Spi &operator=(Spi &&) = delete; - /// @brief Convert a `Spi::Config` into an ESP-IDF `spi_bus_config_t`. - /// @param config High-level SPI bus configuration. + /// @brief Convert high-level SPI bus settings into an ESP-IDF `spi_bus_config_t`. + /// @param config High-level SPI bus settings. /// @return Equivalent ESP-IDF bus configuration. static spi_bus_config_t make_bus_config(const Config &config); - /// @brief Convert a `Spi::DeviceConfig` into an ESP-IDF device config. - /// @param config High-level SPI device configuration. + /// @brief Convert high-level SPI device settings into an ESP-IDF device config. + /// @param config High-level SPI device settings. /// @return Equivalent ESP-IDF device interface configuration. static spi_device_interface_config_t make_device_config(const DeviceConfig &config); diff --git a/components/xiao-esp32s3-sense/example/main/xiao_esp32s3_sense_example.cpp b/components/xiao-esp32s3-sense/example/main/xiao_esp32s3_sense_example.cpp index 455c746e0..b532daebd 100644 --- a/components/xiao-esp32s3-sense/example/main/xiao_esp32s3_sense_example.cpp +++ b/components/xiao-esp32s3-sense/example/main/xiao_esp32s3_sense_example.cpp @@ -85,6 +85,7 @@ extern "C" void app_main(void) { static constexpr float disconnected_led_breathing_period = 1.0f; static constexpr float connected_led_breathing_period = 3.5f; + //! [xiao esp32s3 sense example] auto &sense = espp::XiaoEsp32S3Sense::get(); auto microphone = sense.microphone_pins(); auto sd_card = sense.sd_card_pins(); @@ -118,6 +119,7 @@ extern "C" void app_main(void) { deinitialize_microphone(); return; } + //! [xiao esp32s3 sense example] logger.info("Starting memory monitors"); task_monitor = std::make_unique(espp::TaskMonitor::Config{.period = 30s}); diff --git a/doc/conf_common.py b/doc/conf_common.py index e9b121279..b9593067c 100644 --- a/doc/conf_common.py +++ b/doc/conf_common.py @@ -22,3 +22,9 @@ 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/en/adrc.rst b/doc/en/adrc.rst index 8576ecd32..866e23290 100755 --- a/doc/en/adrc.rst +++ b/doc/en/adrc.rst @@ -28,21 +28,25 @@ This component includes: Choosing a controller --------------------- -+--------------------------+----------------------------------------------+---------------------------------------------+ -| Controller | Best fit | Typical robotics example | -+==========================+==============================================+=============================================+ -| Linear first-order ADRC | Output behaves roughly like a one-pole loop | Motor velocity loop above an inner current | -| | | or torque loop | -+--------------------------+----------------------------------------------+---------------------------------------------+ -| Linear second-order ADRC | Input primarily affects acceleration | Servo position loop, gimbal angle loop, | -| | | heading loop | -+--------------------------+----------------------------------------------+---------------------------------------------+ -| Han first-order ADRC | First-order loop needing nonlinear shaping | Velocity loop with stiction, load steps, | -| | or better large-error behavior | or wide operating range | -+--------------------------+----------------------------------------------+---------------------------------------------+ -| Han second-order ADRC | Second-order loop with large disturbances | Motor-driven joint position control or | -| | and aggressive setpoint changes | heading control on variable terrain | -+--------------------------+----------------------------------------------+---------------------------------------------+ +.. list-table:: + :header-rows: 1 + :widths: 24 38 38 + + * - Controller + - Best fit + - Typical robotics example + * - Linear first-order ADRC + - Output behaves roughly like a one-pole loop + - Motor velocity loop above an inner current or torque loop + * - Linear second-order ADRC + - Input primarily affects acceleration + - Servo position loop, gimbal angle loop, heading loop + * - Han first-order ADRC + - First-order loop needing nonlinear shaping or better large-error behavior + - Velocity loop with stiction, load steps, or wide operating range + * - Han second-order ADRC + - Second-order loop with large disturbances and aggressive setpoint changes + - Motor-driven joint position control or heading control on variable terrain For many motor-control applications, a good starting point is: diff --git a/doc/en/index.rst b/doc/en/index.rst index ab3c34c57..ff9c77cca 100755 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -82,3 +82,4 @@ This is the documentation for esp-idf c++ components, ESPP (`espp ` page shows the use of the +The ``network/socket_example`` page shows the use of the classes provided by the ``socket`` component and runs a scenario-driven self-test which covers teardown, timeout, and reconnect behavior, including: