diff --git a/esp_modem/docs/CMux_collaboration.png b/esp_modem/docs/CMux_collaboration.png index 56d8b9acd..525ccf513 100644 Binary files a/esp_modem/docs/CMux_collaboration.png and b/esp_modem/docs/CMux_collaboration.png differ diff --git a/esp_modem/docs/DCE_DTE_collaboration.png b/esp_modem/docs/DCE_DTE_collaboration.png index 210d6deaf..ef3272a5e 100644 Binary files a/esp_modem/docs/DCE_DTE_collaboration.png and b/esp_modem/docs/DCE_DTE_collaboration.png differ diff --git a/esp_modem/docs/Doxyfile b/esp_modem/docs/Doxyfile index 016651f18..8faf43db4 100644 --- a/esp_modem/docs/Doxyfile +++ b/esp_modem/docs/Doxyfile @@ -829,10 +829,23 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = c_api.h cpp_api.h ../include/esp_modem_api.h \ +INPUT = ../include/esp_modem_api.h \ ../include/esp_modem_c_api_types.h \ ../include/cxx_include/esp_modem_api.hpp \ - ../include/cxx_include/esp_modem_dce.hpp + ../include/cxx_include/esp_modem_dce.hpp \ + ../include/esp_modem_config.h \ + ../include/esp_modem_dce_config.h \ + ../include/cxx_include/esp_modem_dce_factory.hpp \ + ../include/cxx_include/esp_modem_command_library.hpp \ + ../include/cxx_include/esp_modem_dce_module.hpp \ + ../include/cxx_include/esp_modem_dte.hpp \ + ../include/cxx_include/esp_modem_netif.hpp \ + ../include/cxx_include/esp_modem_types.hpp \ + ../include/cxx_include/esp_modem_terminal.hpp \ + ../include/cxx_include/esp_modem_cmux.hpp \ + esp_modem_api_commands.h \ + esp_modem_dce.hpp +# The last two are generated # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -947,7 +960,7 @@ IMAGE_PATH = # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. -INPUT_FILTER = "sed 's/std::unique_ptr<\(.*\)>/\1*/;s/std::shared_ptr<\(.*\)>/\1*/'" +#INPUT_FILTER = "sed 's/std::unique_ptr<\(.*\)>/\1*/;s/std::shared_ptr<\(.*\)>/\1*/'" # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the @@ -1103,7 +1116,7 @@ IGNORE_PREFIX = # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. -GENERATE_HTML = YES +GENERATE_HTML = NO # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of @@ -1658,7 +1671,7 @@ EXTRA_SEARCH_MAPPINGS = # If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. # The default value is: YES. -GENERATE_LATEX = YES +GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of @@ -2459,7 +2472,7 @@ DOT_GRAPH_MAX_NODES = 250 # Minimum value: 0, maximum value: 1000, default value: 0. # This tag requires that the tag HAVE_DOT is set to YES. -MAX_DOT_GRAPH_DEPTH = 10 +MAX_DOT_GRAPH_DEPTH = 3 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not seem @@ -2508,4 +2521,5 @@ DOT_CLEANUP = YES #TEMPLATE_RELATIONS = YES #DOT_GRAPH_MAX_NODES = 100 #MAX_DOT_GRAPH_DEPTH = 0 -#DOT_TRANSPARENT = YES \ No newline at end of file +#DOT_TRANSPARENT = YES + diff --git a/esp_modem/docs/Terminal_inheritance.png b/esp_modem/docs/Terminal_inheritance.png deleted file mode 100644 index b36968009..000000000 Binary files a/esp_modem/docs/Terminal_inheritance.png and /dev/null differ diff --git a/esp_modem/docs/advanced_api.rst b/esp_modem/docs/advanced_api.rst index af0a6a481..1967fc0cc 100644 --- a/esp_modem/docs/advanced_api.rst +++ b/esp_modem/docs/advanced_api.rst @@ -1,15 +1,45 @@ Advanced esp-modem use cases ============================ -Create custom modem instance with DCE factory ---------------------------------------------- +This chapter outlines basic extensibility of the esp-modem component. + +.. _dce_factory: + +Custom instantiation with DCE factory +-------------------------------------- + +It is possible to create a modem handle in many different ways: + +- Build a DCE on top a generic module, user defined module or build the module only (in case the application will only use AT command interface) +- Create the DCE as a shared, unique or a vanilla pointer +- Create a generic DCE or a templated DCE_T of a specific module (this could be one of the supported modules or a user defined module) + +All the functionality is provided by the DCE factory + +.. doxygengroup:: ESP_MODEM_DCE_FACTORY + :members: Create custom module -------------------- +Creating a custom module is necessary if the application needs to use a specific device that is not supported +and their commands differ from any of the supported devices. In this case it is recommended to define a new class +representing this specific device and derive from the :cpp:class:`GenericModule`. In order to instantiate +the appropriate DCE of this module, application could use :ref:`the DCE factory`, but build the DCE with +the specific module, using :cpp:func:`esp_modem::dce_factory::Factory::build`. + +Please refer to the implementation of the existing modules. + Create new communication interface ---------------------------------- +In order to connect to a device using an unsuppoeted interface (e.g. SPI or I2C), it is necessary to implement +a custom DTE object and supply it into :ref:`the DCE factory`. The DCE is typically created in two steps: + +- Define and create the corresponding terminal, which can communicate on the custom interface. This terminal should support basic IO methods defined in :cpp:class:`esp_modem::Terminal` and derive from it. +- Create the DTE which uses the custom Terminal + +Please refer to the implementation of the existing UART DTE. diff --git a/esp_modem/docs/api_docs.rst b/esp_modem/docs/api_docs.rst index b4342c2a0..23506b257 100644 --- a/esp_modem/docs/api_docs.rst +++ b/esp_modem/docs/api_docs.rst @@ -18,6 +18,7 @@ Typical application workflow is to: - Optionally switch back to command mode (again :cpp:func:`esp_modem_set_mode`) - Destroy the DCE handle (sing :cpp:func:`esp_modem_destroy`) +Note the configuration structures for DTE and DCE, needed for creating the DCE instance, is documented in :ref:`api_config` .. _lifecycle_api: @@ -26,6 +27,10 @@ Lifecycle API These functions are used to create, destroy and set modem working mode. +- :cpp:func:`esp_modem_new` +- :cpp:func:`esp_modem_destroy` +- :cpp:func:`esp_modem_set_mode` + .. doxygengroup:: ESP_MODEM_C_API @@ -37,4 +42,13 @@ Modem commands These functions are the actual commands to communicate with the modem using AT command interface. -.. doxygenfile:: c_api.h +.. doxygenfile:: esp_modem_api_commands.h + +.. _api_config: + +Configuration structures +------------------------ + + +.. doxygengroup:: ESP_MODEM_CONFIG + :members: \ No newline at end of file diff --git a/esp_modem/docs/conf.py b/esp_modem/docs/conf.py index 0d0902e85..4bfa938be 100644 --- a/esp_modem/docs/conf.py +++ b/esp_modem/docs/conf.py @@ -9,14 +9,14 @@ import subprocess import sys # General information about the project. -project = u'ESP-MODEM Documentation' +project = u'esp-modem' copyright = u'2016 - 2021, Espressif Systems (Shanghai) Co., Ltd' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. language = 'en' -extensions = ['breathe' ] +extensions = ['breathe'] breathe_projects = {'esp_modem': 'xml'} diff --git a/esp_modem/docs/cxx_api_docs.rst b/esp_modem/docs/cxx_api_docs.rst index f58df63ac..5544c368a 100644 --- a/esp_modem/docs/cxx_api_docs.rst +++ b/esp_modem/docs/cxx_api_docs.rst @@ -3,10 +3,14 @@ C++ API Documentation Similar to the :ref:`c_api`, the basic application workflow consist of -- Construction of the DCE -- Sending (AT) commands -- Switching modes -- Destroying the DCE +.. toctree:: + +- :ref:`Construction of the DCE` +- :ref:`Switching modes` +- :ref:`Sending (AT) commands` +- :ref:`Destroying the DCE` + +.. _cpp_init: Create DTE and DCE ------------------ @@ -16,21 +20,22 @@ Create DTE and DCE .. doxygengroup:: ESP_MODEM_INIT_DCE +.. _cpp_mode_switch: + Mode switching commands ----------------------- .. doxygenclass:: esp_modem::DCE_T :members: +.. _cpp_modem_commands: Modem commands -------------- -Create the DCE object with DCE factory :cpp:func:`esp_modem_new` - -.. doxygenclass:: DCE - :members: +.. include:: cxx_api_links.rst +.. _cpp_destroy: Destroy the DCE --------------- diff --git a/esp_modem/docs/cxx_api_links.rst b/esp_modem/docs/cxx_api_links.rst new file mode 100644 index 000000000..40289e5df --- /dev/null +++ b/esp_modem/docs/cxx_api_links.rst @@ -0,0 +1,13 @@ + +- :cpp:func:`esp_modem::DCE::set_pin` +- :cpp:func:`esp_modem::DCE::read_pin` +- :cpp:func:`esp_modem::DCE::set_echo` +- :cpp:func:`esp_modem::DCE::resume_data_mode` +- :cpp:func:`esp_modem::DCE::set_pdp_context` +- :cpp:func:`esp_modem::DCE::set_command_mode` +- :cpp:func:`esp_modem::DCE::set_cmux` +- :cpp:func:`esp_modem::DCE::get_imsi` +- :cpp:func:`esp_modem::DCE::get_imei` +- :cpp:func:`esp_modem::DCE::get_module_name` +- :cpp:func:`esp_modem::DCE::set_data_mode` +- :cpp:func:`esp_modem::DCE::get_signal_quality` diff --git a/esp_modem/docs/c_api.h b/esp_modem/docs/esp_modem_api_commands.h similarity index 90% rename from esp_modem/docs/c_api.h rename to esp_modem/docs/esp_modem_api_commands.h index f80f92491..826d8c9d7 100644 --- a/esp_modem/docs/c_api.h +++ b/esp_modem/docs/esp_modem_api_commands.h @@ -1,4 +1,5 @@ // cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h +// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst // --- DCE command documentation starts here --- /** * @brief Sends the supplied PIN code diff --git a/esp_modem/docs/cpp_api.h b/esp_modem/docs/esp_modem_dce.hpp similarity index 78% rename from esp_modem/docs/cpp_api.h rename to esp_modem/docs/esp_modem_dce.hpp index feb821bf9..c06c1f08c 100644 --- a/esp_modem/docs/cpp_api.h +++ b/esp_modem/docs/esp_modem_dce.hpp @@ -1,6 +1,8 @@ +// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h +// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst // --- DCE command documentation starts here --- -class DCE: public DCE_T { +class esp_modem::DCE: public DCE_T { public: using DCE_T::DCE_T; @@ -9,6 +11,7 @@ public: + /** * @brief Sends the supplied PIN code * diff --git a/esp_modem/docs/generate_docs b/esp_modem/docs/generate_docs index 70e9dffae..0e007ada5 100755 --- a/esp_modem/docs/generate_docs +++ b/esp_modem/docs/generate_docs @@ -1,2 +1,20 @@ +# Cleanup the generated html +rm -rf html +# Generate C++ API header of the DCE +cat ../include/generate/esp_modem_command_declare.inc | clang++ -E -P -CC -xc++ -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > esp_modem_dce.hpp + +# Generate C API header of the modem_api.h +cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > esp_modem_api_commands.h + +# RST with links to C++ API +cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst + +# Run doxygen +doxygen + +# Generate the docs python -u -m sphinx.cmd.build -b html . html + +# Cleanup the doxygen xml's +rm -rf xml diff --git a/esp_modem/docs/index.rst b/esp_modem/docs/index.rst index c5e7f8090..9a87192f6 100644 --- a/esp_modem/docs/index.rst +++ b/esp_modem/docs/index.rst @@ -1,5 +1,5 @@ -ESP-MODEM Documentation -======================= +ESP-MODEM Programmers manual +============================ .. toctree:: @@ -8,4 +8,4 @@ ESP-MODEM Documentation C++ interface Advanced use cases Internal design - + Internal implementation diff --git a/esp_modem/docs/internal_design.md b/esp_modem/docs/internal_design.md index 5ec0e2aaf..379855de6 100644 --- a/esp_modem/docs/internal_design.md +++ b/esp_modem/docs/internal_design.md @@ -3,45 +3,14 @@ ## Design decisions * Use C++ with additional C API - - | esp-modem in C | esp-modem in C++ | - |----------------|---------------| -``` - +2282 - -3908 -``` * Use exceptions - Use macro wrapper over `try-catch` blocks when exceptions off (use `abort()` if `THROW()`) -| exceptions off | exceptions on | -|----------------|---------------| -``` -Difference is counted as - , i.e. a positive number means that is larger. -Total sizes of : Difference - DRAM .data size: 10996 bytes 10996 - DRAM .bss size: 12552 bytes 12488 +64 -Used static DRAM: 23548 bytes ( 157188 available, 13.0% used) 23484 +64 ( -64 available, +0 total) -Used static IRAM: 54145 bytes ( 76927 available, 41.3% used) 54093 +52 ( -52 available, +0 total) - Flash code: 603979 bytes 595551 +8428 - Flash rodata: 187772 bytes 177852 +9920 -Total image size:~ 869444 bytes (.bin may be padded larger) 850980 +18464 -``` -| exceptions on | RTTI on | -|----------------|---------------| -``` -Total sizes of : Difference - DRAM .data size: 10996 bytes 10996 - DRAM .bss size: 12552 bytes 12552 -Used static DRAM: 23548 bytes ( 157188 available, 13.0% used) 23548 ( +0 available, +0 total) -Used static IRAM: 54145 bytes ( 76927 available, 41.3% used) 54145 ( +0 available, +0 total) - Flash code: 605331 bytes 603979 +1352 - Flash rodata: 196788 bytes 187772 +9016 -Total image size:~ 879812 bytes (.bin may be padded larger) 869444 +10368 -``` * Initializes and allocates in the constructor (might throw) - easier code with exceptions ON, with exceptions OFF alloc/init failures are not treated as runtime error (program aborts) - break down long initialization in constructor into more private methods + * Implements different devices using inheritance from `GenericModule`, which is the most general implementation of a common modem - Internally uses templates with device specialization (modeled as `DCE`) which could be used as well for some special cases, such as implantation of a minimal device (ModuleIf), add new AT commands (oOnly in compile time), or using the Module with DTE only (no DCE, no Netif) for sending AT commands without network @@ -57,12 +26,11 @@ The diagram describes how the DCE class collaborates with DTE, PPP and the devic Terminal is a class which can read or write data, and can handle callbacks when data are available. UART specialization is provided implementing these method using the uart driver. -![TerminalInheritance](Terminal_inheritance.png) - ## CMUX terminal -The below diagram depicts the idea of using CMUX terminal mode using the CMux class which is a terminal +The below diagram depicts the idea of using CMUX terminal mode using the CMuxInstance class which is a terminal (it implements the basic read/write methods) interfacing arbitrary number of virtual terminals, -but at the same time it is also composed of another terminal, the real terminal, which is multiplexed. +but at the same time it is also composed of CMux class, which consumes the original terminal and uses its read/write methods +to multiplex the terminal. ![CMUX Terminal](CMux_collaboration.png) diff --git a/esp_modem/docs/internal_docs.rst b/esp_modem/docs/internal_docs.rst new file mode 100644 index 000000000..c1c64f679 --- /dev/null +++ b/esp_modem/docs/internal_docs.rst @@ -0,0 +1,85 @@ +DCE Internal implementation +=========================== + +This chapter provides a detailed description of the classes and building blocks of the esp-modem component and their responsibilities. + +The esp-modem actually implements the DCE class, which in turn aggregates these thee units: + +- :ref:`DTE` to communicate with the device on a specific Terminal interface such as UART. +- :ref:`Netif` to provide the network connectivity +- :ref:`Module` to define the specific command library + +------------ + +.. doxygengroup:: ESP_MODEM_DCE + :members: + +.. _dte_impl: + +DTE abstraction +--------------- + +DTE is a basic unit to talk to the module using a Terminal interface. It also implements and uses the CMUX to multiplex +terminals. Besides the DTE documentation, this section also refers to the + +- :ref:`Terminal interface` +- :ref:`CMUX implementation` + + +------------ + +.. doxygengroup:: ESP_MODEM_DTE + :members: + +.. _term_impl: + +Terminal interface +^^^^^^^^^^^^^^^^^^ + +.. doxygengroup:: ESP_MODEM_TERMINAL + :members: + +.. _cmux_impl: + +CMUX implementation +^^^^^^^^^^^^^^^^^^^ + +.. doxygengroup:: ESP_MODEM_CMUX + :members: + +.. _netif_impl: + +Netif +----- + +.. doxygengroup:: ESP_MODEM_NETIF + :members: + +.. _module_impl: + +Module abstraction +------------------ + +.. doxygengroup:: ESP_MODEM_MODULE + :members: + +Command library +^^^^^^^^^^^^^^^ + +This is a namespace holding a library of typical AT commands used by supported devices. +Please refer to the :ref:`c_api` for the list of supported commands. + +.. doxygengroup:: ESP_MODEM_DCE_COMMAND + :members: + + +Modem types +----------- + +.. doxygengroup:: ESP_MODEM_TYPES + :members: + + + + + diff --git a/esp_modem/include/cxx_include/esp_modem_api.hpp b/esp_modem/include/cxx_include/esp_modem_api.hpp index d08d30791..6dc86e4d9 100644 --- a/esp_modem/include/cxx_include/esp_modem_api.hpp +++ b/esp_modem/include/cxx_include/esp_modem_api.hpp @@ -26,9 +26,6 @@ struct esp_modem_dce_config; namespace esp_modem { class DTE; -using dce_config = ::esp_modem_dce_config; -using dte_config = ::esp_modem_dte_config; - typedef struct esp_netif_obj esp_netif_t; @@ -40,6 +37,9 @@ typedef struct esp_netif_obj esp_netif_t; * @{ */ +using dce_config = ::esp_modem_dce_config; +using dte_config = ::esp_modem_dte_config; + /** * @brief Create UART DTE * @param config DTE configuration @@ -52,7 +52,7 @@ std::shared_ptr create_uart_dte(const dte_config *config); /** * @defgroup ESP_MODEM_INIT_DCE ESP_MODEM Initialization API for DCE - * @brief Create DCE's + * @brief ESP_MODEM Initialization API for DCE */ /** @addtogroup ESP_MODEM_INIT_DCE * @{ diff --git a/esp_modem/include/cxx_include/esp_modem_cmux.hpp b/esp_modem/include/cxx_include/esp_modem_cmux.hpp index ce7bab2b0..636faaf10 100644 --- a/esp_modem/include/cxx_include/esp_modem_cmux.hpp +++ b/esp_modem/include/cxx_include/esp_modem_cmux.hpp @@ -49,6 +49,10 @@ enum class cmux_state { */ class CMuxInstance; +/** + * @brief CMux class which consumes the original terminal and creates multiple virtual terminals from it. + * This class is not usable applicable as a DTE terminal + */ class CMux { public: explicit CMux(std::unique_ptr t, std::unique_ptr b, size_t buff_size): @@ -77,6 +81,10 @@ private: int instance; }; +/** + * @brief This represents a specific instance of a CMUX virtual terminal. This class also implements Terminal interface + * and as such could be used as a DTE's terminal. + */ class CMuxInstance: public Terminal { public: explicit CMuxInstance(std::shared_ptr parent, int i): cmux(std::move(parent)), instance(i) {} diff --git a/esp_modem/include/cxx_include/esp_modem_dce.hpp b/esp_modem/include/cxx_include/esp_modem_dce.hpp index 5b07608ea..89abcdb84 100644 --- a/esp_modem/include/cxx_include/esp_modem_dce.hpp +++ b/esp_modem/include/cxx_include/esp_modem_dce.hpp @@ -21,6 +21,18 @@ namespace esp_modem { +/** + * @defgroup ESP_MODEM_DCE + * @brief Definition of DCE abstraction + */ +/** @addtogroup ESP_MODEM_DCE + * @{ + */ + + +/** + * @brief Helper class responsible for switching modes of the DCE's + */ class DCE_Mode { public: DCE_Mode(): mode(modem_mode::COMMAND_MODE) {} @@ -33,7 +45,10 @@ private: }; - +/** + * @brief General DCE class templated on a specific module. It is responsible for all the necessary transactions + * related to switching modes and consequent synergy with aggregated objects of DTE, Netif and a specific Module + */ template class DCE_T { static_assert(std::is_base_of::value, "DCE must be instantiated with Module class only"); @@ -72,7 +87,10 @@ protected: DCE_Mode mode; }; - +/** + * @brief Common abstraction of the modem DCE, specialized by the GenericModule which is a parent class for the supported + * defices and most common modems, as well. + */ class DCE: public DCE_T { public: @@ -90,6 +108,10 @@ public: }; +/** + * @} + */ + } // esp_modem #endif // _ESP_MODEM_DCE_HPP_ \ No newline at end of file diff --git a/esp_modem/include/cxx_include/esp_modem_dce_factory.hpp b/esp_modem/include/cxx_include/esp_modem_dce_factory.hpp index ef6530ba3..df4de10da 100644 --- a/esp_modem/include/cxx_include/esp_modem_dce_factory.hpp +++ b/esp_modem/include/cxx_include/esp_modem_dce_factory.hpp @@ -15,10 +15,24 @@ #ifndef _ESP_MODEM_DCE_FACTORY_HPP_ #define _ESP_MODEM_DCE_FACTORY_HPP_ +/** + * @defgroup ESP_MODEM_DCE_FACTORY + * @brief DCE modem factory + */ + + namespace esp_modem::dce_factory { using config = ::esp_modem_dce_config; +/** @addtogroup ESP_MODEM_DCE_FACTORY +* @{ +*/ + + +/** + * @brief Helper class for creating a uder define pointer in a specific way, either as a plain pointer, shared_ptr or unique_ptr + */ class FactoryHelper { public: static std::unique_ptr create_pdp_context(std::string &apn); @@ -43,6 +57,9 @@ public: }; +/** + * @brief Builder class for building a DCE_T in a specific way, either form a Module object or by default from the DTE and netif + */ template class Builder { static_assert(std::is_base_of::value, "Builder must be used only for Module classes"); @@ -87,23 +104,46 @@ private: esp_netif_t *netif; }; +/** + * @brief Specific modem choice when creating by the Factory + */ enum class Modem { - SIM800, - SIM7600, - BG96, - MinModule + GenericModule, /*!< Default generic module with the most common commands */ + SIM800, /*!< Derived from the GenericModule with specifics applied to SIM800 model */ + SIM7600, /*!< Derived from the GenericModule, specifics applied to SIM7600 model */ + BG96, /*!< Derived from the GenericModule, specifics applied to BG69 model */ }; +/** + * @brief Factory class for creating virtual DCE objects based on the configuration of the supplied module. + * This could also be used to create a custom module or a DCE_T, provided user app derives from this factory. + */ class Factory { public: explicit Factory(Modem modem): m(modem) {} + /** + * @brief Create a default unique_ptr DCE in a specific way (from the module) + * @tparam Module Specific Module used in this DCE + * @tparam Args Arguments to the builder, i.e. constructor of esp_modem::DCE_T class + * @param cfg DCE configuration structure ::esp_modem_dte_config + * @param args typically a DTE object and a netif handle for PPP network + * @return unique_ptr DCE of the created DCE on success + */ template static std::unique_ptr build_unique(const config *cfg, Args&&... args) { return build_generic_DCE>(cfg, std::forward(args)...); } + /** + * @brief Create a DCE + * @tparam Module Specific Module used in this DCE + * @tparam Args Arguments to the builder, i.e. constructor of esp_modem::DCE_T class + * @param cfg DCE configuration structure ::esp_modem_dte_config + * @param args typically a DTE object and a netif handle for PPP network + * @return DCE pointer the created DCE on success + */ template static DCE* build(const config *cfg, Args&&... args) { @@ -128,12 +168,21 @@ public: return build_shared_module(cfg, std::forward(args)...); case Modem::BG96: return build_shared_module(cfg, std::forward(args)...); - case Modem::MinModule: + case Modem::GenericModule: + return build_shared_module(cfg, std::forward(args)...); + default: break; } return nullptr; } + /** + * @brief Create a default unique_ptr DCE generically, with the chosen module derived from the GenericModule + * @tparam Args Arguments to the builder, i.e. constructor of esp_modem::DCE_T class + * @param cfg DCE configuration structure ::esp_modem_dte_config + * @param args typically a DTE object and a netif handle for PPP network + * @return unique_ptr DCE of the created DCE on success + */ template std::unique_ptr build_unique(const config *cfg, Args&&... args) { @@ -144,7 +193,9 @@ public: return build_unique(cfg, std::forward(args)...); case Modem::BG96: return build_unique(cfg, std::forward(args)...); - case Modem::MinModule: + case Modem::GenericModule: + return build_unique(cfg, std::forward(args)...); + default: break; } return nullptr; @@ -169,6 +220,11 @@ protected: } }; +/** + * @} + */ + } // namespace esp_modem::dce_factory + #endif // _ESP_MODEM_DCE_FACTORY_HPP_ diff --git a/esp_modem/include/cxx_include/esp_modem_dce_module.hpp b/esp_modem/include/cxx_include/esp_modem_dce_module.hpp index f3aafaa44..1640b12e7 100644 --- a/esp_modem/include/cxx_include/esp_modem_dce_module.hpp +++ b/esp_modem/include/cxx_include/esp_modem_dce_module.hpp @@ -24,10 +24,23 @@ namespace esp_modem { +/** + * @defgroup ESP_MODEM_MODULE + * @brief Definition of modules representing specific modem devices + */ + +/** @addtogroup ESP_MODEM_MODULE +* @{ +*/ + enum class command_result; class DTE; struct PdpContext; +/** + * @brief This is a basic building block for custom modules as well as for the supported modules in the esp-modem component + * It derives from the ModuleIf. + */ class GenericModule: public ModuleIf { public: explicit GenericModule(std::shared_ptr dte, std::unique_ptr pdp): @@ -72,24 +85,37 @@ protected: }; // Definitions of other modules + +/** + * @brief Specific definition of the SIM7600 module + */ class SIM7600: public GenericModule { using GenericModule::GenericModule; public: command_result get_module_name(std::string& name) override; }; +/** + * @brief Specific definition of the SIM800 module + */ class SIM800: public GenericModule { using GenericModule::GenericModule; public: command_result get_module_name(std::string& name) override; }; +/** + * @brief Specific definition of the BG96 module + */ class BG96: public GenericModule { using GenericModule::GenericModule; public: command_result get_module_name(std::string& name) override; }; +/** + * @} + */ } // namespace esp_modem diff --git a/esp_modem/include/cxx_include/esp_modem_dte.hpp b/esp_modem/include/cxx_include/esp_modem_dte.hpp index ec827ae7a..81b8f8e37 100644 --- a/esp_modem/include/cxx_include/esp_modem_dte.hpp +++ b/esp_modem/include/cxx_include/esp_modem_dte.hpp @@ -26,14 +26,37 @@ namespace esp_modem { +/** + * @defgroup ESP_MODEM_DTE + * @brief Definition of DTE and related classes + */ +/** @addtogroup ESP_MODEM_DTE +* @{ +*/ + +/** + * DTE (Data Terminal Equipment) class + */ class DTE : public CommandableIf { public: explicit DTE(std::unique_ptr t); ~DTE() = default; + /** + * @brief Writing to the underlying terminal + * @param data Data pointer to write + * @param len Data len to write + * @return number of bytes written + */ int write(uint8_t *data, size_t len) { return term->write(data, len); } + /** + * @brief Reading from the underlying terminal + * @param d Returning the data pointer of the received payload + * @param len Length of the data payload + * @return number of bytes read + */ int read(uint8_t **d, size_t len) { auto data_to_read = std::min(len, buffer_size); auto data = buffer.get(); @@ -92,6 +115,9 @@ private: std::function on_data; }; +/** + * @} + */ } // namespace esp_modem diff --git a/esp_modem/include/cxx_include/esp_modem_netif.hpp b/esp_modem/include/cxx_include/esp_modem_netif.hpp index f2afbbea1..85ffd9f41 100644 --- a/esp_modem/include/cxx_include/esp_modem_netif.hpp +++ b/esp_modem/include/cxx_include/esp_modem_netif.hpp @@ -30,16 +30,37 @@ struct ppp_netif_driver { Netif *ppp; }; +/** + * @defgroup ESP_MODEM_NETIF + * @brief Network interface layer of the esp-modem + */ + +/** @addtogroup ESP_MODEM_NETIF +* @{ +*/ + +/** + * @brief Network interface class responsible to glue the esp-netif to the modem's DCE + */ class Netif { public: explicit Netif(std::shared_ptr e, esp_netif_t *netif); ~Netif(); + /** + * @brief Start the network interface + */ void start(); + /** + * @brief Blocks until the network interface closes + */ void wait_until_ppp_exits(); + /** + * @brief Stop the network interface + */ void stop(); private: @@ -59,6 +80,10 @@ private: static const size_t PPP_EXIT = signal_group::bit1; }; +/** + * @} + */ + } // namespace esp_modem #endif // _ESP_MODEM_NETIF_HPP diff --git a/esp_modem/include/cxx_include/esp_modem_terminal.hpp b/esp_modem/include/cxx_include/esp_modem_terminal.hpp index ae293f646..98b4560a3 100644 --- a/esp_modem/include/cxx_include/esp_modem_terminal.hpp +++ b/esp_modem/include/cxx_include/esp_modem_terminal.hpp @@ -26,37 +26,64 @@ namespace esp_modem { +/** + * @defgroup ESP_MODEM_TERMINAL + * @brief Definition of an abstract terminal to be attached to DTE class + */ + +/** @addtogroup ESP_MODEM_TERMINAL +* @{ +*/ + +/** + * @brief Terminal errors + */ enum class terminal_error { BUFFER_OVERFLOW, CHECKSUM_ERROR, UNEXPECTED_CONTROL_FLOW, }; +/** + * @brief Terminal interface. All communication interfaces must comply this interface in order to be used as a DTE + */ class Terminal { public: virtual ~Terminal() = default; -// virtual void set_data_cb(std::function f) { on_data = std::move(f); } - void set_error_cb(std::function f) { on_error = std::move(f); } + virtual void set_read_cb(std::function f) { on_data = std::move(f); } + /** + * @brief Writes data to the terminal + * @param data Data pointer + * @param len Data len + * @return length of data written + */ virtual int write(uint8_t *data, size_t len) = 0; + /** + * @brief Read from the terminal. This function doesn't block, but return all available data. + * @param data Data pointer to store the read payload + * @param len Maximum data len to read + * @return length of data actually read + */ virtual int read(uint8_t *data, size_t len) = 0; virtual void start() = 0; virtual void stop() = 0; - virtual size_t max_virtual_terms() { return 1; } - protected: -// std::function on_data; std::function on_data; std::function on_error; }; +/** + * @} + */ + } // namespace esp_modem #endif // _ESP_MODEM_TERMINAL_HPP_ diff --git a/esp_modem/include/cxx_include/esp_modem_types.hpp b/esp_modem/include/cxx_include/esp_modem_types.hpp index 281869305..ae73cd814 100644 --- a/esp_modem/include/cxx_include/esp_modem_types.hpp +++ b/esp_modem/include/cxx_include/esp_modem_types.hpp @@ -22,21 +22,40 @@ namespace esp_modem { +/** + * @defgroup ESP_MODEM_TYPES + * @brief Basic type definitions used in esp-modem + */ + +/** @addtogroup ESP_MODEM_TYPES +* @{ +*/ + +/** + * @brief Modem working mode + */ enum class modem_mode { UNDEF, - COMMAND_MODE, - DATA_MODE, - CMUX_MODE + COMMAND_MODE, /*!< Command mode -- the modem is supposed to send AT commands in this mode */ + DATA_MODE, /*!< Data mode -- the modem communicates with network interface on PPP protocol */ + CMUX_MODE /*!< CMUX (Multiplex mode) -- Simplified CMUX mode, which creates two virtual terminals, + * assigning one solely to command interface and the other to the data mode */ }; +/** + * @brief Module command result + */ enum class command_result { - OK, - FAIL, - TIMEOUT + OK, /*!< The command completed successfully */ + FAIL, /*!< The command explicitly failed */ + TIMEOUT /*!< The device didn't respond in the specified timeline */ }; typedef std::function got_line_cb; +/** + * @brief PDP context used for configuring and setting the data mode up + */ struct PdpContext { explicit PdpContext(std::string apn) : apn(std::move(apn)) {} size_t context_id = 1; @@ -44,18 +63,44 @@ struct PdpContext { std::string apn; }; +/** + * @brief Interface for classes eligible to send AT commands (Modules, DCEs, DTEs) + */ class CommandableIf { public: + /** + * @brief Sends custom AT command + * @param command Command to be sent + * @param got_line callback if a line received + * @param time_ms timeout in milliseconds + * @return OK, FAIL or TIMEOUT + */ virtual command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms) = 0; }; +/** + * @brief Interface for classes implementing a module for the modem + */ class ModuleIf { public: + /** + * @brief Sets the data mode up (provides the necessary configuration to connect to the cellular network + * @return true on success + */ virtual bool setup_data_mode() = 0; + /** + * @brief Sets the operation mode + * @param mode Desired mode + * @return true on success + */ virtual bool set_mode(modem_mode mode) = 0; }; +/** + * @} + */ + } // namespace esp_modem #endif // _ESP_MODEM_TYPES_HPP_ diff --git a/esp_modem/include/esp_modem_config.h b/esp_modem/include/esp_modem_config.h index 0729fd4a5..aa020b2b7 100644 --- a/esp_modem/include/esp_modem_config.h +++ b/esp_modem/include/esp_modem_config.h @@ -17,6 +17,15 @@ #include "driver/uart.h" #include "esp_modem_dce_config.h" +/** + * @defgroup ESP_MODEM_CONFIG + * @brief Configuration structures for DTE and DCE + */ + +/** @addtogroup ESP_MODEM_CONFIG + * @{ + */ + /** * @brief Modem flow control type * @@ -27,6 +36,10 @@ typedef enum { ESP_MODEM_FLOW_CONTROL_HW } esp_modem_flow_ctrl_t; +/** + * @brief DTE configuration structure + * + */ struct esp_modem_dte_config { uart_port_t port_num; /*!< UART port number */ uart_word_length_t data_bits; /*!< Data bits of UART */ @@ -74,4 +87,8 @@ struct esp_modem_dte_config { typedef struct esp_modem_dte_config esp_modem_dte_config_t; +/** + * @} + */ + #endif // _ESP_MODEM_CONFIG_H_ diff --git a/esp_modem/include/esp_modem_dce_config.h b/esp_modem/include/esp_modem_dce_config.h index 138fb0550..6f1931dfd 100644 --- a/esp_modem/include/esp_modem_dce_config.h +++ b/esp_modem/include/esp_modem_dce_config.h @@ -15,10 +15,14 @@ #ifndef _ESP_MODEM_DCE_CONFIG_H_ #define _ESP_MODEM_DCE_CONFIG_H_ -struct esp_modem_dce_config { - const char* apn; -}; +/** @addtogroup ESP_MODEM_CONFIG + * @{ + */ +/** + * @brief ESP Modem DCE Default Configuration + * + */ #define ESP_MODEM_DCE_DEFAULT_CONFIG(APN) \ { \ .apn = APN \ @@ -26,4 +30,16 @@ struct esp_modem_dce_config { typedef struct esp_modem_dce_config esp_modem_dce_config_t; +/** + * @brief DCE configuration structure + */ +struct esp_modem_dce_config { + const char* apn; /*!< APN: Logical name of the Access point */ +}; + +/** + * @} + */ + + #endif // _ESP_MODEM_DCE_CONFIG_H_ diff --git a/esp_modem/include/generate/esp_modem_command_declare.inc b/esp_modem/include/generate/esp_modem_command_declare.inc index e2748c778..d2d29f6aa 100644 --- a/esp_modem/include/generate/esp_modem_command_declare.inc +++ b/esp_modem/include/generate/esp_modem_command_declare.inc @@ -132,17 +132,19 @@ ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, MUX_ARG, IN #ifdef GENERATE_DOCS // cat ../include/generate/esp_modem_command_declare.inc | clang++ -E -P -CC -xc++ -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' // cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h +// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst // --- DCE command documentation starts here --- #ifdef __cplusplus -class DCE: public DCE_T { +class esp_modem::DCE: public DCE_T { public: using DCE_T::DCE_T; #define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) return_type name (__VA_ARGS__); +#elif defined(GENERATE_RST_LINKS) +#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) NL- :cpp:func:`esp_modem::DCE::name` #else #define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) return_type esp_modem_ ## name (__VA_ARGS__); #endif - DECLARE_ALL_COMMAND_APIS() #ifdef __cplusplus