diff --git a/examples/protocols/pppos_client/components/modem/CMakeLists.txt b/examples/protocols/pppos_client/components/modem/CMakeLists.txt index 543d22b2a4..50fa1a4b7b 100644 --- a/examples/protocols/pppos_client/components/modem/CMakeLists.txt +++ b/examples/protocols/pppos_client/components/modem/CMakeLists.txt @@ -3,8 +3,10 @@ set(srcs "src/esp_modem.c" "src/esp_modem_netif.c" "src/esp_modem_compat.c" "src/sim800.c" + "src/sim7600.c" "src/bg96.c") idf_component_register(SRCS "${srcs}" INCLUDE_DIRS include + PRIV_INCLUDE_DIRS private_include REQUIRES driver) diff --git a/examples/protocols/pppos_client/components/modem/component.mk b/examples/protocols/pppos_client/components/modem/component.mk index 24cab8b637..d3afe77680 100644 --- a/examples/protocols/pppos_client/components/modem/component.mk +++ b/examples/protocols/pppos_client/components/modem/component.mk @@ -1,3 +1,3 @@ COMPONENT_ADD_INCLUDEDIRS := include - +COMPONENT_PRIV_INCLUDEDIRS := private_include COMPONENT_SRCDIRS := src diff --git a/examples/protocols/pppos_client/components/modem/include/sim7600.h b/examples/protocols/pppos_client/components/modem/include/sim7600.h new file mode 100644 index 0000000000..4fbb9a1b12 --- /dev/null +++ b/examples/protocols/pppos_client/components/modem/include/sim7600.h @@ -0,0 +1,33 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_modem_dce_service.h" +#include "esp_modem.h" + +/** + * @brief Create and initialize SIM7600 object + * + * @param dte Modem DTE object + * @return modem_dce_t* Modem DCE object + */ +modem_dce_t *sim7600_init(modem_dte_t *dte); + +#ifdef __cplusplus +} +#endif diff --git a/examples/protocols/pppos_client/components/modem/private_include/bg96_private.h b/examples/protocols/pppos_client/components/modem/private_include/bg96_private.h new file mode 100644 index 0000000000..6b245fc8fd --- /dev/null +++ b/examples/protocols/pppos_client/components/modem/private_include/bg96_private.h @@ -0,0 +1,37 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +/** + * @brief Macro defined for error checking + * + */ +#define DCE_CHECK(a, str, goto_tag, ...) \ + do \ + { \ + if (!(a)) \ + { \ + ESP_LOGE(DCE_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + goto goto_tag; \ + } \ + } while (0) + +/** + * @brief BG96 Modem + * + */ +typedef struct { + void *priv_resource; /*!< Private resource */ + modem_dce_t parent; /*!< DCE parent class */ +} bg96_modem_dce_t; diff --git a/examples/protocols/pppos_client/components/modem/src/bg96.c b/examples/protocols/pppos_client/components/modem/src/bg96.c index 2625613ccb..0924efd78f 100644 --- a/examples/protocols/pppos_client/components/modem/src/bg96.c +++ b/examples/protocols/pppos_client/components/modem/src/bg96.c @@ -15,32 +15,11 @@ #include #include "esp_log.h" #include "bg96.h" +#include "bg96_private.h" #define MODEM_RESULT_CODE_POWERDOWN "POWERED DOWN" -/** - * @brief Macro defined for error checking - * - */ static const char *DCE_TAG = "bg96"; -#define DCE_CHECK(a, str, goto_tag, ...) \ - do \ - { \ - if (!(a)) \ - { \ - ESP_LOGE(DCE_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - goto goto_tag; \ - } \ - } while (0) - -/** - * @brief BG96 Modem - * - */ -typedef struct { - void *priv_resource; /*!< Private resource */ - modem_dce_t parent; /*!< DCE parent class */ -} bg96_modem_dce_t; /** * @brief Handle response from AT+CSQ diff --git a/examples/protocols/pppos_client/components/modem/src/esp_modem.c b/examples/protocols/pppos_client/components/modem/src/esp_modem.c index 928fbbfa51..27d25c2caa 100644 --- a/examples/protocols/pppos_client/components/modem/src/esp_modem.c +++ b/examples/protocols/pppos_client/components/modem/src/esp_modem.c @@ -62,6 +62,21 @@ typedef struct { int pattern_queue_size; /*!< UART pattern queue size */ } esp_modem_dte_t; +/** + * @brief Returns true if the supplied string contains only CR or LF + * + * @param str string to check + * @param len length of string + */ +static inline bool is_only_cr_lf(const char *str, uint32_t len) +{ + for (int i=0; iparent.dce; MODEM_CHECK(dce, "DTE has not yet bind with DCE", err); const char *line = (const char *)(esp_dte->buffer); + size_t len = strlen(line); /* Skip pure "\r\n" lines */ - if (strlen(line) > 2) { + if (len > 2 && !is_only_cr_lf(line, len)) { MODEM_CHECK(dce->handle_line, "no handler for line", err_handle); MODEM_CHECK(dce->handle_line(dce, line) == ESP_OK, "handle line failed", err_handle); } diff --git a/examples/protocols/pppos_client/components/modem/src/sim7600.c b/examples/protocols/pppos_client/components/modem/src/sim7600.c new file mode 100644 index 0000000000..3cf8907de5 --- /dev/null +++ b/examples/protocols/pppos_client/components/modem/src/sim7600.c @@ -0,0 +1,90 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include "esp_log.h" +#include "bg96.h" +#include "bg96_private.h" + +/** + * @brief This module supports SIM7600 module, which has a very similar interface + * to the BG96, so it just references most of the handlers from BG96 and implements + * only those that differ. + */ +static const char *DCE_TAG = "sim7600"; + +/** + * @brief Handle response from AT+CBC + */ +static esp_err_t sim7600_handle_cbc(modem_dce_t *dce, const char *line) +{ + esp_err_t err = ESP_FAIL; + bg96_modem_dce_t *bg96_dce = __containerof(dce, bg96_modem_dce_t, parent); + if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) { + err = esp_modem_process_command_done(dce, MODEM_STATE_SUCCESS); + } else if (strstr(line, MODEM_RESULT_CODE_ERROR)) { + err = esp_modem_process_command_done(dce, MODEM_STATE_FAIL); + } else if (!strncmp(line, "+CBC", strlen("+CBC"))) { + /* store value of bcs, bcl, voltage */ + int32_t **cbc = bg96_dce->priv_resource; + int32_t volts = 0, fraction = 0; + /* +CBC: V*/ + sscanf(line, "+CBC: %d.%dV", &volts, &fraction); + /* Since the "read_battery_status()" API (besides voltage) returns also values for BCS, BCL (charge status), + * which are not applicable to this modem, we return -1 to indicate invalid value + */ + *cbc[0] = -1; // BCS + *cbc[1] = -1; // BCL + *cbc[2] = volts*1000 + fraction; + err = ESP_OK; + } + return err; +} + +/** + * @brief Get battery status + * + * @param dce Modem DCE object + * @param bcs Battery charge status + * @param bcl Battery connection level + * @param voltage Battery voltage + * @return esp_err_t + * - ESP_OK on success + * - ESP_FAIL on error + */ +static esp_err_t sim7600_get_battery_status(modem_dce_t *dce, uint32_t *bcs, uint32_t *bcl, uint32_t *voltage) +{ + modem_dte_t *dte = dce->dte; + bg96_modem_dce_t *bg96_dce = __containerof(dce, bg96_modem_dce_t, parent); + uint32_t *resource[3] = {bcs, bcl, voltage}; + bg96_dce->priv_resource = resource; + dce->handle_line = sim7600_handle_cbc; + DCE_CHECK(dte->send_cmd(dte, "AT+CBC\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err); + DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "inquire battery status failed", err); + ESP_LOGD(DCE_TAG, "inquire battery status ok"); + return ESP_OK; +err: + return ESP_FAIL; +} + +/** + * @brief Create and initialize SIM7600 object + * + */ +modem_dce_t *sim7600_init(modem_dte_t *dte) +{ + modem_dce_t *dce = bg96_init(dte); + dte->dce->get_battery_status = sim7600_get_battery_status; + return dce; +} diff --git a/examples/protocols/pppos_client/main/Kconfig.projbuild b/examples/protocols/pppos_client/main/Kconfig.projbuild index 0618de0b82..ca02b41d12 100644 --- a/examples/protocols/pppos_client/main/Kconfig.projbuild +++ b/examples/protocols/pppos_client/main/Kconfig.projbuild @@ -14,6 +14,10 @@ menu "Example Configuration" bool "BG96" help Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module. + config EXAMPLE_MODEM_DEVICE_SIM7600 + bool "SIM7600" + help + SIM7600 is Multi-Band LTE-TDD/LTE-FDD/HSPA+ and GSM/GPRS/EDGE module endchoice config EXAMPLE_MODEM_PPP_AUTH_USERNAME diff --git a/examples/protocols/pppos_client/main/pppos_client_main.c b/examples/protocols/pppos_client/main/pppos_client_main.c index 179590b7eb..5af7fea8be 100644 --- a/examples/protocols/pppos_client/main/pppos_client_main.c +++ b/examples/protocols/pppos_client/main/pppos_client_main.c @@ -17,6 +17,7 @@ #include "esp_log.h" #include "sim800.h" #include "bg96.h" +#include "sim7600.h" #define BROKER_URL "mqtt://mqtt.eclipse.org" @@ -261,6 +262,8 @@ void app_main(void) dce = sim800_init(dte); #elif CONFIG_EXAMPLE_MODEM_DEVICE_BG96 dce = bg96_init(dte); +#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 + dce = sim7600_init(dte); #else #error "Unsupported DCE" #endif