diff --git a/components/driver/rmt/rmt_rx.c b/components/driver/rmt/rmt_rx.c index c861e42c024..b9686286a16 100644 --- a/components/driver/rmt/rmt_rx.c +++ b/components/driver/rmt/rmt_rx.c @@ -500,7 +500,7 @@ static bool IRAM_ATTR rmt_isr_handle_rx_done(rmt_rx_channel_t *rx_chan) rmt_ll_rx_enable(hal->regs, channel_id, false); uint32_t offset = rmt_ll_rx_get_memory_writer_offset(hal->regs, channel_id); // sanity check - assert(offset > rx_chan->mem_off); + assert(offset >= rx_chan->mem_off); rmt_ll_rx_set_mem_owner(hal->regs, channel_id, RMT_LL_MEM_OWNER_SW); // copy the symbols to user space size_t stream_symbols = offset - rx_chan->mem_off; diff --git a/docs/en/api-reference/peripherals/rmt.rst b/docs/en/api-reference/peripherals/rmt.rst index 85077ca78b4..7fbf7303420 100644 --- a/docs/en/api-reference/peripherals/rmt.rst +++ b/docs/en/api-reference/peripherals/rmt.rst @@ -518,7 +518,7 @@ Application Examples * RMT transactions in queue: :example:`peripherals/rmt/musical_buzzer` * RMT based stepper motor with S-curve algorithm: : :example:`peripherals/rmt/stepper_motor` * RMT infinite loop for driving DShot ESC: :example:`peripherals/rmt/dshot_esc` -* RMT simulate 1-wire protocol (take DS18B20 as example): :example:`peripherals/rmt/onewire_ds18b20` +* RMT simulate 1-wire protocol (take DS18B20 as example): :example:`peripherals/rmt/onewire` API Reference ------------- diff --git a/examples/peripherals/rmt/onewire_ds18b20/CMakeLists.txt b/examples/peripherals/rmt/onewire/CMakeLists.txt similarity index 89% rename from examples/peripherals/rmt/onewire_ds18b20/CMakeLists.txt rename to examples/peripherals/rmt/onewire/CMakeLists.txt index cdd8daafe60..8e815472af9 100644 --- a/examples/peripherals/rmt/onewire_ds18b20/CMakeLists.txt +++ b/examples/peripherals/rmt/onewire/CMakeLists.txt @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(onewire_ds18b20) +project(onewire) diff --git a/examples/peripherals/rmt/onewire/README.md b/examples/peripherals/rmt/onewire/README.md new file mode 100644 index 00000000000..f218e4689ba --- /dev/null +++ b/examples/peripherals/rmt/onewire/README.md @@ -0,0 +1,74 @@ +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | + +# Advanced RMT Transmit & Receive Example -- Simulate 1-Wire Bus + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +RMT peripheral has independent transmit and receive channels. We can simulate the [1-Wire](https://www.analog.com/en/technical-articles/guide-to-1wire-communication.html) bus by attaching a pair of transmit and receive channel to the same GPIO, and turning on the open-drain mode of the GPIO pad. + +We've made the 1-Wire protocol implementation into a component called `onewire_bus`, which has been uploaded to the [component registry](https://components.espressif.com/components/espressif/onewire_bus). + +This example demonstrates how to use that `onewire_bus` library to read temperature from the [DS18B20](https://www.analog.com/media/en/technical-documentation/data-sheets/ds18b20.pdf) sensor. Likewise, the DS18B20 device is also made as a single component and pushed to the [component registry](https://components.espressif.com/components/espressif/ds18b20). + +One of the amazing feature that offered by the `onewire_bus` driver is that, is can support enumerate the devices on the bus, thus you can connect multiple DS18B20 sensors to the same bus and read their temperature one by one. + +## How to Use Example + +### Hardware Required + +* A development board with any supported Espressif SOC chip (see `Supported Targets` table above) +* One or more DS18B20 sensors connected to the same bus by a 4.7 KΩ pull-up resistor + +Connection : + +```plain +┌──────────────────────────┐ +│ 3.3V├───────┬─────────────┬──────────────────────┐ +│ │ ┌┴┐ │VDD │VDD +│ ESP Board │ 4.7k│ │ ┌──────┴──────┐ ┌──────┴──────┐ +│ │ └┬┘ DQ│ │ DQ│ │ +│ ONEWIRE_GPIO_PIN├───────┴──┬───┤ DS18B20 │ ┌───┤ DS18B20 │ ...... +│ │ └───│-------------│────┴───│-------------│── +│ │ └──────┬──────┘ └──────┬──────┘ +│ │ │GND │GND +│ GND├─────────────────────┴──────────────────────┘ +└──────────────────────────┘ +``` + +The GPIO number used in this example can be changed according to your board, by the macro `EXAMPLE_ONEWIRE_BUS_GPIO` defined in [onewire_example_main.c](main/onewire_example_main.c). + +> **Note** +> Parasite power mode is not supported, you have to connect VDD pin to make DS18B20 functional. + +### Build and Flash + +Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + +## Console Output + +```plain +I (340) main_task: Started on CPU0 +I (350) main_task: Calling app_main() +I (350) gpio: GPIO[0]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 +I (360) gpio: GPIO[0]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0 +I (370) example: 1-Wire bus installed on GPIO0 +I (370) example: Device iterator created, start searching... +I (490) example: Found a DS18B20[0], address: 070822502019FC28 +I (590) example: Found a DS18B20[1], address: FC0921C076034628 +I (590) example: Searching done, 2 DS18B20 device(s) found +I (1620) example: temperature read from DS18B20[0]: 22.50C +I (2430) example: temperature read from DS18B20[1]: 22.81C +I (3440) example: temperature read from DS18B20[0]: 22.50C +I (4250) example: temperature read from DS18B20[1]: 22.81C +I (5260) example: temperature read from DS18B20[0]: 22.50C +I (6070) example: temperature read from DS18B20[1]: 22.81C +``` + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/peripherals/rmt/onewire/main/CMakeLists.txt b/examples/peripherals/rmt/onewire/main/CMakeLists.txt new file mode 100644 index 00000000000..cc6bae17cd7 --- /dev/null +++ b/examples/peripherals/rmt/onewire/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "onewire_example_main.c" + INCLUDE_DIRS ".") diff --git a/examples/peripherals/rmt/onewire/main/idf_component.yml b/examples/peripherals/rmt/onewire/main/idf_component.yml new file mode 100644 index 00000000000..1ca3e8bca85 --- /dev/null +++ b/examples/peripherals/rmt/onewire/main/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + ds18b20: "^0.1.0" diff --git a/examples/peripherals/rmt/onewire/main/onewire_example_main.c b/examples/peripherals/rmt/onewire/main/onewire_example_main.c new file mode 100644 index 00000000000..d3c3b414b65 --- /dev/null +++ b/examples/peripherals/rmt/onewire/main/onewire_example_main.c @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_check.h" +#include "onewire_bus.h" +#include "ds18b20.h" + +static const char *TAG = "example"; + +#define EXAMPLE_ONEWIRE_BUS_GPIO 0 +#define EXAMPLE_ONEWIRE_MAX_DS18B20 2 + +void app_main(void) +{ + // install new 1-wire bus + onewire_bus_handle_t bus; + onewire_bus_config_t bus_config = { + .bus_gpio_num = EXAMPLE_ONEWIRE_BUS_GPIO, + }; + onewire_bus_rmt_config_t rmt_config = { + .max_rx_bytes = 10, // 1byte ROM command + 8byte ROM number + 1byte device command + }; + ESP_ERROR_CHECK(onewire_new_bus_rmt(&bus_config, &rmt_config, &bus)); + ESP_LOGI(TAG, "1-Wire bus installed on GPIO%d", EXAMPLE_ONEWIRE_BUS_GPIO); + + int ds18b20_device_num = 0; + ds18b20_device_handle_t ds18b20s[EXAMPLE_ONEWIRE_MAX_DS18B20]; + onewire_device_iter_handle_t iter = NULL; + onewire_device_t next_onewire_device; + esp_err_t search_result = ESP_OK; + + // create 1-wire device iterator, which is used for device search + ESP_ERROR_CHECK(onewire_new_device_iter(bus, &iter)); + ESP_LOGI(TAG, "Device iterator created, start searching..."); + do { + search_result = onewire_device_iter_get_next(iter, &next_onewire_device); + if (search_result == ESP_OK) { // found a new device, let's check if we can upgrade it to a DS18B20 + ds18b20_config_t ds_cfg = {}; + if (ds18b20_new_device(&next_onewire_device, &ds_cfg, &ds18b20s[ds18b20_device_num]) == ESP_OK) { + ESP_LOGI(TAG, "Found a DS18B20[%d], address: %016llX", ds18b20_device_num, next_onewire_device.address); + ds18b20_device_num++; + if (ds18b20_device_num >= EXAMPLE_ONEWIRE_MAX_DS18B20) { + ESP_LOGI(TAG, "Max DS18B20 number reached, stop searching..."); + break; + } + } else { + ESP_LOGI(TAG, "Found an unknown device, address: %016llX", next_onewire_device.address); + } + } + } while (search_result != ESP_ERR_NOT_FOUND); + ESP_ERROR_CHECK(onewire_del_device_iter(iter)); + ESP_LOGI(TAG, "Searching done, %d DS18B20 device(s) found", ds18b20_device_num); + + // set resolution for all DS18B20s + for (int i = 0; i < ds18b20_device_num; i++) { + // set resolution + ESP_ERROR_CHECK(ds18b20_set_resolution(ds18b20s[i], DS18B20_RESOLUTION_12B)); + } + + // get temperature from sensors one by one + float temperature; + while (1) { + vTaskDelay(pdMS_TO_TICKS(200)); + + for (int i = 0; i < ds18b20_device_num; i ++) { + ESP_ERROR_CHECK(ds18b20_trigger_temperature_conversion(ds18b20s[i])); + ESP_ERROR_CHECK(ds18b20_get_temperature(ds18b20s[i], &temperature)); + ESP_LOGI(TAG, "temperature read from DS18B20[%d]: %.2fC", i, temperature); + } + } +} diff --git a/examples/peripherals/rmt/onewire_ds18b20/pytest_onewire_ds18b20.py b/examples/peripherals/rmt/onewire/pytest_onewire.py similarity index 50% rename from examples/peripherals/rmt/onewire_ds18b20/pytest_onewire_ds18b20.py rename to examples/peripherals/rmt/onewire/pytest_onewire.py index 8e86c6c1313..fc7c045a6b3 100644 --- a/examples/peripherals/rmt/onewire_ds18b20/pytest_onewire_ds18b20.py +++ b/examples/peripherals/rmt/onewire/pytest_onewire.py @@ -11,8 +11,7 @@ @pytest.mark.esp32c6 @pytest.mark.esp32h2 @pytest.mark.generic -def test_onewire_ds18b20_example(dut: Dut) -> None: - dut.expect_exact('onewire_rmt: RMT Tx channel created for 1-wire bus') - dut.expect_exact('onewire_rmt: RMT Rx channel created for 1-wire bus') - dut.expect_exact('example: 1-wire bus installed') - dut.expect_exact('example: 1-wire bus deleted') +def test_onewire_example(dut: Dut) -> None: + dut.expect_exact('example: 1-Wire bus installed on GPIO') + dut.expect_exact('example: Device iterator created, start searching') + dut.expect_exact('example: Searching done') diff --git a/examples/peripherals/rmt/onewire_ds18b20/README.md b/examples/peripherals/rmt/onewire_ds18b20/README.md deleted file mode 100644 index b59afa3c9b2..00000000000 --- a/examples/peripherals/rmt/onewire_ds18b20/README.md +++ /dev/null @@ -1,90 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | - -# RMT Transmit & Receive Example -- 1-Wire bus - -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -RMT peripheral has both transmit and receive channels. Connecting one transmit channel and one receive channel to the same GPIO and put the GPIO in open-drain mode can simulate bi-directional single wire protocols, such as [1-Wire protocol](https://www.maximintegrated.com/en/design/technical-documents/tutorials/1/1796.html). - -This example demonstrates how to use RMT to simulate 1-Wire bus and read temperatrue from [DS18B20](https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf). - -## How to Use Example - -### Hardware Required - -* A development board with any supported Espressif SOC chip (see `Supported Targets` table above) -* Several DS18B20 temperature sensors and a 4.7kohm pullup resistor - -Connection : - -``` -┌──────────────────────────┐ -│ 3.3V├───────┬─────────────┬──────────────────────┐ -│ │ ┌┴┐ │VDD │VDD -│ ESP32 Board │ 4.7k│ │ ┌──────┴──────┐ ┌──────┴──────┐ -│ │ └┬┘ DQ│ │ DQ│ │ -│ ONEWIRE_GPIO_PIN├───────┴──┬───┤ DS18B20 │ ┌───┤ DS18B20 │ ...... -│ │ └───│-------------│────┴───│-------------│── -│ │ └──────┬──────┘ └──────┬──────┘ -│ │ │GND │GND -│ GND├─────────────────────┴──────────────────────┘ -└──────────────────────────┘ -``` - -The GPIO number used in this example can be changed according to your board, by the macro `EXAMPLE_ONEWIRE_GPIO_PIN` defined in [onewire_ds18b20_example_main.c](main/onewire_ds18b20_example_main.c). - -*Note*: Parasite power mode is not supported currently by this example, you have to connect VDD pin to make DS18B20 functional. - -### Build and Flash - -Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. - -## Console Output - -If there are some DS18B20s on the bus: - -``` -I (327) cpu_start: Starting scheduler on PRO CPU. -I (0) cpu_start: Starting scheduler on APP CPU. -I (338) gpio: GPIO[5]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 -I (348) onewire_rmt: RMT Tx channel created for 1-wire bus -I (358) gpio: GPIO[5]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0 -I (358) onewire_rmt: RMT Rx channel created for 1-wire bus -I (368) example: 1-wire bus installed -I (418) example: found device with rom id 28FF30BE21170317 -I (458) example: found device with rom id 28FF297E211703A1 -I (498) example: found device with rom id 28FF6F7921170352 -I (508) example: 3 devices found on 1-wire bus -I (2518) example: temperature of device 28FF30BE21170317: 27.00C -I (2528) example: temperature of device 28FF297E211703A1: 26.81C -I (2538) example: temperature of device 28FF6F7921170352: 26.50C -I (3548) example: temperature of device 28FF30BE21170317: 26.94C -I (3558) example: temperature of device 28FF297E211703A1: 26.75C -I (3568) example: temperature of device 28FF6F7921170352: 26.44C -``` - -If there is no DS18B20 on the bus: - -``` -I (327) cpu_start: Starting scheduler on PRO CPU. -I (0) cpu_start: Starting scheduler on APP CPU. -I (337) gpio: GPIO[5]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 -I (347) onewire_rmt: RMT Tx channel created for 1-wire bus -I (357) gpio: GPIO[5]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0 -I (357) onewire_rmt: RMT Rx channel created for 1-wire bus -I (367) example: 1-wire bus installed -E (377) onewire_rmt: no device present on 1-wire bus -I (377) example: 0 device found on 1-wire bus -I (387) gpio: GPIO[5]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 -I (397) gpio: GPIO[5]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 -I (397) example: 1-wire bus deleted -``` - -## Troubleshooting - -For any technical queries, please open an [issue] (https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/CMakeLists.txt b/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/CMakeLists.txt deleted file mode 100644 index 05df56811ac..00000000000 --- a/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "onewire_bus_rmt.c" "onewire_bus.c" - INCLUDE_DIRS "." - PRIV_REQUIRES driver) diff --git a/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus.c b/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus.c deleted file mode 100644 index 8bfa126510d..00000000000 --- a/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include "esp_check.h" -#include "esp_log.h" -#include "onewire_bus.h" - -static const char *TAG = "onewire"; - -struct onewire_rom_search_context_t { - onewire_bus_handle_t bus_handle; - - uint8_t last_device_flag; - uint16_t last_discrepancy; - uint8_t rom_number[8]; -}; - -// Algorithm inspired by https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/187.html - -static const uint8_t dscrc_table[] = { - 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, - 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, - 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, - 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, - 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, - 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, - 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, - 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, - 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, - 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, - 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, - 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, - 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, - 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, - 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, - 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53 -}; - -uint8_t onewire_check_crc8(uint8_t *input, size_t input_size) -{ - uint8_t crc8 = 0; - - for (size_t i = 0; i < input_size; i ++) { - crc8 = dscrc_table[crc8 ^ input[i]]; - } - - return crc8; -} - -esp_err_t onewire_rom_search_context_create(onewire_bus_handle_t handle, onewire_rom_search_context_handler_t *context_out) -{ - ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid 1-wire handle"); - ESP_RETURN_ON_FALSE(context_out, ESP_ERR_INVALID_ARG, TAG, "invalid context handler pointer"); - - struct onewire_rom_search_context_t *context = calloc(1, sizeof(struct onewire_rom_search_context_t)); - if (!context) { - return ESP_ERR_NO_MEM; - } - - context->bus_handle = handle; - *context_out = context; - - return ESP_OK; -} - -esp_err_t onewire_rom_search_context_delete(onewire_rom_search_context_handler_t context) -{ - ESP_RETURN_ON_FALSE(context, ESP_ERR_INVALID_ARG, TAG, "invalid context handler pointer"); - - free(context); - - return ESP_OK; -} - -esp_err_t onewire_rom_search(onewire_rom_search_context_handler_t context) -{ - ESP_RETURN_ON_FALSE(context, ESP_ERR_INVALID_ARG, TAG, "invalid context handler pointer"); - - uint8_t last_zero = 0; - - if (!context->last_device_flag) { - if (onewire_bus_reset(context->bus_handle) != ESP_OK) { // no device present - return ESP_ERR_NOT_FOUND; - } - - // send rom search command and start search algorithm - ESP_RETURN_ON_ERROR(onewire_bus_write_bytes(context->bus_handle, (uint8_t[]){ONEWIRE_CMD_SEARCH_ROM}, 1), - TAG, "error while sending search rom command"); - - for (uint16_t rom_bit_index = 0; rom_bit_index < 64; rom_bit_index ++) { - uint8_t rom_byte_index = rom_bit_index / 8; - uint8_t rom_bit_mask = 1 << (rom_bit_index % 8); // calculate byte index and bit mask in advance for convenience - - uint8_t rom_bit, rom_bit_complement; - ESP_RETURN_ON_ERROR(onewire_bus_read_bit(context->bus_handle, &rom_bit), TAG, "error while reading rom bit"); // write 1 bit to read from the bus - ESP_RETURN_ON_ERROR(onewire_bus_read_bit(context->bus_handle, &rom_bit_complement), - TAG, "error while reading rom bit"); // read a bit and its complement - - uint8_t search_direction; - if (rom_bit && rom_bit_complement) { // No devices participating in search. - ESP_LOGE(TAG, "no devices participating in search"); - return ESP_ERR_NOT_FOUND; - } else { - if (rom_bit != rom_bit_complement) { // There are only 0s or 1s in the bit of the participating ROM numbers. - search_direction = rom_bit; // just go ahead - } else { // There are both 0s and 1s in the current bit position of the participating ROM numbers. This is a discrepancy. - if (rom_bit_index < context->last_discrepancy) { // current id bit is before the last discrepancy bit - search_direction = (context->rom_number[rom_byte_index] & rom_bit_mask) ? 0x01 : 0x00; // follow previous way - } else { - search_direction = (rom_bit_index == context->last_discrepancy) ? 0x01 : 0x00; // search for 0 bit first - } - - if (search_direction == 0) { // record zero's position in last zero - last_zero = rom_bit_index; - } - } - - if (search_direction == 1) { // set corrsponding rom bit by serach direction - context->rom_number[rom_byte_index] |= rom_bit_mask; - } else { - context->rom_number[rom_byte_index] &= ~rom_bit_mask; - } - - ESP_RETURN_ON_ERROR(onewire_bus_write_bit(context->bus_handle, search_direction), - TAG, "error while writing direction bit"); // set search direction - } - } - } else { - ESP_LOGD(TAG, "1-wire rom search finished"); - return ESP_FAIL; - } - - // if the search was successful - context->last_discrepancy = last_zero; - if (context->last_discrepancy == 0) { // last zero loops back to the first bit - context->last_device_flag = true; - } - - if (onewire_check_crc8(context->rom_number, 7) != context->rom_number[7]) { // check crc - ESP_LOGE(TAG, "bad crc checksum of device with id " ONEWIRE_ROM_ID_STR, ONEWIRE_ROM_ID(context->rom_number)); - return ESP_ERR_INVALID_CRC; - } - - return ESP_OK; -} - -esp_err_t onewire_rom_get_number(onewire_rom_search_context_handler_t context, uint8_t *rom_number_out) -{ - ESP_RETURN_ON_FALSE(context, ESP_ERR_INVALID_ARG, TAG, "invalid context pointer"); - ESP_RETURN_ON_FALSE(rom_number_out, ESP_ERR_INVALID_ARG, TAG, "invalid rom_number pointer"); - - memcpy(rom_number_out, context->rom_number, sizeof(context->rom_number)); - - return ESP_OK; -} diff --git a/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus.h b/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus.h deleted file mode 100644 index 3cb0ea511c6..00000000000 --- a/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include "esp_err.h" -#include "onewire_bus_rmt.h" - -#define ONEWIRE_CMD_SEARCH_ROM 0xF0 -#define ONEWIRE_CMD_READ_ROM 0x33 -#define ONEWIRE_CMD_MATCH_ROM 0x55 -#define ONEWIRE_CMD_SKIP_ROM 0xCC -#define ONEWIRE_CMD_ALARM_SEARCH_ROM 0xEC - -#define ONEWIRE_ROM_ID(id) (id)[0], (id)[1], (id)[2], (id)[3], (id)[4], (id)[5], (id)[6], (id)[7] -#define ONEWIRE_ROM_ID_STR "%02X%02X%02X%02X%02X%02X%02X%02X" - -/** - * @brief Type of 1-wire ROM search algorithm context - * - */ -typedef struct onewire_rom_search_context_t *onewire_rom_search_context_handler_t; - -/** - * @brief Calculate Dallas CRC value of given buffer - * - * @param[in] input Input buffer to calculate CRC value - * @param[in] input_size Size of input buffer - * @return CRC result of input buffer - */ -uint8_t onewire_check_crc8(uint8_t *input, size_t input_size); - -/** - * @brief Create context for 1-wire ROM search algorithm - * - * @param[in] handle 1-wire handle used for ROM search - * @param[out] context_out Created context for ROM search algorithm - * @return - * - ESP_OK 1-wire ROM search context is created successfully. - * - ESP_ERR_INVALID_ARG Invalid argument. - */ -esp_err_t onewire_rom_search_context_create(onewire_bus_handle_t handle, onewire_rom_search_context_handler_t *context_out); - -/** - * @brief Delete context for 1-wire ROM search algorithm - * - * @param[in] context Context for ROM search algorithm - * @return - * - ESP_OK 1-wire ROM search context is deleted successfully. - * - ESP_ERR_INVALID_ARG Invalid argument. - */ -esp_err_t onewire_rom_search_context_delete(onewire_rom_search_context_handler_t context); - -/** - * @brief Search next device on 1-wire bus - * - * @param[in] context Context for ROM search algorithm - * @return - * - ESP_OK Successfully found a device - * - ESP_ERR_NOT_FOUND There are no device on the bus - * - ESP_ERR_INVALID_CRC Bad CRC value of found device - * - ESP_FAIL Reached last device on the bus, search algorighm finishes - */ -esp_err_t onewire_rom_search(onewire_rom_search_context_handler_t context); - -/** - * @brief Get device ROM number from ROM search context - * - * @param[in] context Context for ROM search algorithm - * @param[out] rom_number_out Device ROM number - * @return - * - ESP_OK Get ROM numbuer from 1-wire ROM search context success. - * - ESP_ERR_INVALID_ARG Invalid argument. - */ -esp_err_t onewire_rom_get_number(onewire_rom_search_context_handler_t context, uint8_t *rom_number_out); diff --git a/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus_rmt.c b/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus_rmt.c deleted file mode 100644 index af0e6a232c8..00000000000 --- a/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus_rmt.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "esp_check.h" -#include "driver/rmt_tx.h" -#include "driver/rmt_rx.h" -#include "driver/rmt_types.h" -#include "driver/rmt_encoder.h" -#include "onewire_bus_rmt.h" - -static const char *TAG = "onewire_rmt"; - -/** - * @brief RMT resolution for 1-wire bus, in Hz - * - */ -#define ONEWIRE_RMT_RESOLUTION_HZ 1000000 - -/** - * @brief 1-wire bus timing parameters, in us (1/ONEWIRE_RMT_RESOLUTION_HZ) - * - */ -#define ONEWIRE_RESET_PULSE_DURATION 500 // duration of reset bit -#define ONEWIRE_RESET_WAIT_DURATION 200 // how long should master wait for device to show its presence -#define ONEWIRE_RESET_PRESENSE_WAIT_DURATION_MIN 15 // minimum duration for master to wait device to show its presence -#define ONEWIRE_RESET_PRESENSE_DURATION_MIN 60 // minimum duration for master to recognize device as present - -#define ONEWIRE_SLOT_START_DURATION 2 // bit start pulse duration -#define ONEWIRE_SLOT_BIT_DURATION 60 // duration for each bit to transmit -// refer to https://www.maximintegrated.com/en/design/technical-documents/app-notes/3/3829.html for more information -#define ONEWIRE_SLOT_RECOVERY_DURATION 2 // recovery time between each bit, should be longer in parasite power mode -#define ONEWIRE_SLOT_BIT_SAMPLE_TIME 15 // how long after bit start pulse should the master sample from the bus - -/* -Reset Pulse: - - | RESET_PULSE | RESET_WAIT_DURATION | - | _DURATION | | - | | | | RESET | | - | | * | | _PRESENSE | | - | | | | _DURATION | | -------────┐ ┌─────┐ ┌───────------- - │ │ │ │ - │ │ │ │ - │ │ │ │ - └─────────────┘ └───────────┘ -*: RESET_PRESENSE_WAIT_DURATION - -Write 1 bit: - - | SLOT_START | SLOT_BIT | SLOT_RECOVERY | NEXT - | _DURATION | _DURATION | _DURATION | SLOT - | | | | -------────┐ ┌───────────────────────────────------ - │ │ - │ │ - │ │ - └────────────┘ - -Write 0 bit: - - | SLOT_START | SLOT_BIT | SLOT_RECOVERY | NEXT - | _DURATION | _DURATION | _DURATION | SLOT - | | | | -------────┐ ┌───────────────────------ - │ │ - │ │ - │ │ - └────────────────────────┘ - -Read 1 bit: - - - | SLOT_START | SLOT_BIT_DURATION | SLOT_RECOVERY | NEXT - | _DURATION | | _DURATION | SLOT - | | SLOT_BIT_ | | | - | | SAMPLE_TIME | | | -------────┐ ┌────────────────────────────────────────------ - │ │ - │ │ - │ │ - └────────────┘ - -Read 0 bit: - - | SLOT_START | SLOT_BIT_DURATION | SLOT_RECOVERY | NEXT - | _DURATION | | _DURATION | SLOT - | | SLOT_BIT_ | | | - | | SAMPLE_TIME | | | -------────┐ | | ┌───────────────────────------ - │ | │ - │ | PULLED DOWN │ - │ | BY DEVICE │ - └─────────────────────────────┘ -*/ - -struct onewire_bus_t { - rmt_channel_handle_t tx_channel; /*!< rmt tx channel handler */ - rmt_encoder_handle_t tx_bytes_encoder; /*!< used to encode commands and data */ - rmt_encoder_handle_t tx_copy_encoder; /*!< used to encode reset pulse and bits */ - - rmt_channel_handle_t rx_channel; /*!< rmt rx channel handler */ - rmt_symbol_word_t *rx_symbols; /*!< hold rmt raw symbols */ - - size_t max_rx_bytes; /*!< buffer size in byte for single receive transaction */ - - QueueHandle_t receive_queue; -}; - -const static rmt_symbol_word_t onewire_bit0_symbol = { - .level0 = 0, - .duration0 = ONEWIRE_SLOT_START_DURATION + ONEWIRE_SLOT_BIT_DURATION, - .level1 = 1, - .duration1 = ONEWIRE_SLOT_RECOVERY_DURATION -}; - -const static rmt_symbol_word_t onewire_bit1_symbol = { - .level0 = 0, - .duration0 = ONEWIRE_SLOT_START_DURATION, - .level1 = 1, - .duration1 = ONEWIRE_SLOT_BIT_DURATION + ONEWIRE_SLOT_RECOVERY_DURATION -}; - -const static rmt_symbol_word_t onewire_reset_pulse_symbol = { - .level0 = 0, - .duration0 = ONEWIRE_RESET_PULSE_DURATION, - .level1 = 1, - .duration1 = ONEWIRE_RESET_WAIT_DURATION -}; - -const static rmt_transmit_config_t onewire_rmt_tx_config = { - .loop_count = 0, // no transfer loop - .flags.eot_level = 1 // onewire bus should be released in IDLE -}; - -const static rmt_receive_config_t onewire_rmt_rx_config = { - .signal_range_min_ns = 1000000000 / ONEWIRE_RMT_RESOLUTION_HZ, - .signal_range_max_ns = (ONEWIRE_RESET_PULSE_DURATION + ONEWIRE_RESET_WAIT_DURATION) * 1000 -}; - -static bool onewire_rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *edata, void *user_data) -{ - BaseType_t task_woken = pdFALSE; - struct onewire_bus_t *handle = (struct onewire_bus_t *)user_data; - - xQueueSendFromISR(handle->receive_queue, edata, &task_woken); - - return task_woken; -} - -/* -[0].0 means symbol[0].duration0 - -First reset pulse after rmt channel init: - -Bus is low | Reset | Wait | Device | Bus Idle -after init | Pulse | | Presense | - ┌──────┐ ┌─────------ - │ │ │ - │ │ │ - │ │ │ -------─────────────┘ └──────────┘ - 1 2 3 - - [0].1 [0].0 [1].1 [1].0 - - -Following reset pulses: - -Bus is high | Reset | Wait | Device | Bus Idle -after init | Pulse | | Presense | -------──────┐ ┌──────┐ ┌─────------ - │ │ │ │ - │ │ │ │ - │ │ │ │ - └───────┘ └──────────┘ - 1 2 3 4 - - [0].0 [0].1 [1].0 [1].1 -*/ - -static bool onewire_rmt_check_presence_pulse(rmt_symbol_word_t *rmt_symbols, size_t symbol_num) -{ - if (symbol_num >= 2) { // there should be at lease 2 symbols(3 or 4 edges) - if (rmt_symbols[0].level1 == 1) { // bus is high before reset pulse - if (rmt_symbols[0].duration1 > ONEWIRE_RESET_PRESENSE_WAIT_DURATION_MIN && - rmt_symbols[1].duration0 > ONEWIRE_RESET_PRESENSE_DURATION_MIN) { - return true; - } - } else { // bus is low before reset pulse(first pulse after rmt channel init) - if (rmt_symbols[0].duration0 > ONEWIRE_RESET_PRESENSE_WAIT_DURATION_MIN && - rmt_symbols[1].duration1 > ONEWIRE_RESET_PRESENSE_DURATION_MIN) { - return true; - } - } - } - - ESP_LOGE(TAG, "no device present on 1-wire bus"); - return false; -} - -static void onewire_rmt_decode_data(rmt_symbol_word_t *rmt_symbols, size_t symbol_num, uint8_t *decoded_bytes) -{ - size_t byte_pos = 0, bit_pos = 0; - for (size_t i = 0; i < symbol_num; i ++) { - if (rmt_symbols[i].duration0 > ONEWIRE_SLOT_BIT_SAMPLE_TIME) { // 0 bit - decoded_bytes[byte_pos] &= ~(1 << bit_pos); // LSB first - } else { // 1 bit - decoded_bytes[byte_pos] |= 1 << bit_pos; - } - - bit_pos ++; - if (bit_pos >= 8) { - bit_pos = 0; - byte_pos ++; - } - } -} - -esp_err_t onewire_new_bus_rmt(onewire_rmt_config_t *config, onewire_bus_handle_t *handle_out) -{ - ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "invalid config pointer"); - ESP_RETURN_ON_FALSE(handle_out, ESP_ERR_INVALID_ARG, TAG, "invalid handle pointer"); - - esp_err_t ret = ESP_OK; - - struct onewire_bus_t *handle = calloc(1, sizeof(struct onewire_bus_t)); - ESP_GOTO_ON_FALSE(handle, ESP_ERR_NO_MEM, err, TAG, "memory allocation for 1-wire bus handler failed"); - - // create rmt bytes encoder to transmit 1-wire commands and data - rmt_bytes_encoder_config_t bytes_encoder_config = { - .bit0 = onewire_bit0_symbol, - .bit1 = onewire_bit1_symbol, - .flags.msb_first = 0 - }; - ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &handle->tx_bytes_encoder), - err, TAG, "create data tx encoder failed"); - - // create rmt copy encoder to transmit 1-wire reset pulse or bits - rmt_copy_encoder_config_t copy_encoder_config = {}; - ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &handle->tx_copy_encoder), - err, TAG, "create reset pulse tx encoder failed"); - - // create rmt rx channel - rmt_rx_channel_config_t onewire_rx_channel_cfg = { - .clk_src = RMT_CLK_SRC_DEFAULT, - .gpio_num = config->gpio_pin, -#if SOC_RMT_SUPPORT_RX_PINGPONG - .mem_block_symbols = 64, // when the chip is ping-pong capable, we can use less rx memory blocks -#else - .mem_block_symbols = config->max_rx_bytes * 8, -#endif - .resolution_hz = ONEWIRE_RMT_RESOLUTION_HZ, // in us - }; - ESP_GOTO_ON_ERROR(rmt_new_rx_channel(&onewire_rx_channel_cfg, &handle->rx_channel), - err, TAG, "create rmt rx channel failed"); - ESP_LOGI(TAG, "RMT Tx channel created for 1-wire bus"); - - // create rmt tx channel after rx channel - rmt_tx_channel_config_t onewire_tx_channel_cfg = { - .clk_src = RMT_CLK_SRC_DEFAULT, - .gpio_num = config->gpio_pin, - .mem_block_symbols = 64, // ping-pong is always avaliable on tx channel, save hardware memory blocks - .resolution_hz = ONEWIRE_RMT_RESOLUTION_HZ, // in us - .trans_queue_depth = 4, - .flags.io_loop_back = true, // make tx channel coexist with rx channel on the same gpio pin - .flags.io_od_mode = true // enable open-drain mode for 1-wire bus - }; - ESP_GOTO_ON_ERROR(rmt_new_tx_channel(&onewire_tx_channel_cfg, &handle->tx_channel), - err, TAG, "create rmt tx channel failed"); - ESP_LOGI(TAG, "RMT Rx channel created for 1-wire bus"); - - // allocate rmt rx symbol buffer - handle->rx_symbols = malloc(config->max_rx_bytes * sizeof(rmt_symbol_word_t) * 8); - ESP_GOTO_ON_FALSE(handle->rx_symbols, ESP_ERR_NO_MEM, err, TAG, "memory allocation for rx symbol buffer failed"); - handle->max_rx_bytes = config->max_rx_bytes; - - handle->receive_queue = xQueueCreate(1, sizeof(rmt_rx_done_event_data_t)); - ESP_GOTO_ON_FALSE(handle->receive_queue, ESP_ERR_NO_MEM, err, TAG, "receive queue creation failed"); - - // register rmt rx done callback - rmt_rx_event_callbacks_t cbs = { - .on_recv_done = onewire_rmt_rx_done_callback - }; - ESP_GOTO_ON_ERROR(rmt_rx_register_event_callbacks(handle->rx_channel, &cbs, handle), - err, TAG, "enable rmt rx channel failed"); - - // enable rmt channels - ESP_GOTO_ON_ERROR(rmt_enable(handle->rx_channel), err, TAG, "enable rmt rx channel failed"); - ESP_GOTO_ON_ERROR(rmt_enable(handle->tx_channel), err, TAG, "enable rmt tx channel failed"); - - *handle_out = handle; - return ESP_OK; - -err: - if (handle) { - onewire_del_bus(handle); - } - - return ret; -} - -esp_err_t onewire_del_bus(onewire_bus_handle_t handle) -{ - ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid 1-wire handle"); - - if (handle->tx_bytes_encoder) { - rmt_del_encoder(handle->tx_bytes_encoder); - } - if (handle->tx_copy_encoder) { - rmt_del_encoder(handle->tx_copy_encoder); - } - if (handle->rx_channel) { - rmt_disable(handle->rx_channel); - rmt_del_channel(handle->rx_channel); - } - if (handle->tx_channel) { - rmt_disable(handle->tx_channel); - rmt_del_channel(handle->tx_channel); - } - if (handle->receive_queue) { - vQueueDelete(handle->receive_queue); - } - if (handle->rx_symbols) { - free(handle->rx_symbols); - } - free(handle); - - return ESP_OK; -} - -esp_err_t onewire_bus_reset(onewire_bus_handle_t handle) -{ - ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid 1-wire handle"); - - // send reset pulse while receive presence pulse - ESP_RETURN_ON_ERROR(rmt_receive(handle->rx_channel, handle->rx_symbols, sizeof(rmt_symbol_word_t) * 2, &onewire_rmt_rx_config), - TAG, "1-wire reset pulse receive failed"); - ESP_RETURN_ON_ERROR(rmt_transmit(handle->tx_channel, handle->tx_copy_encoder, &onewire_reset_pulse_symbol, sizeof(onewire_reset_pulse_symbol), &onewire_rmt_tx_config), - TAG, "1-wire reset pulse transmit failed"); - - // wait and check presence pulse - bool is_present = false; - rmt_rx_done_event_data_t rmt_rx_evt_data; - if (xQueueReceive(handle->receive_queue, &rmt_rx_evt_data, pdMS_TO_TICKS(1000)) == pdPASS) { - is_present = onewire_rmt_check_presence_pulse(rmt_rx_evt_data.received_symbols, rmt_rx_evt_data.num_symbols); - } - - return is_present ? ESP_OK : ESP_ERR_NOT_FOUND; -} - -esp_err_t onewire_bus_write_bytes(onewire_bus_handle_t handle, const uint8_t *tx_data, uint8_t tx_data_size) -{ - ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid 1-wire handle"); - ESP_RETURN_ON_FALSE(tx_data && tx_data_size != 0, ESP_ERR_INVALID_ARG, TAG, "invalid tx buffer or buffer size"); - - // transmit data - ESP_RETURN_ON_ERROR(rmt_transmit(handle->tx_channel, handle->tx_bytes_encoder, tx_data, tx_data_size, &onewire_rmt_tx_config), - TAG, "1-wire data transmit failed"); - - // wait the transmission to complete - ESP_RETURN_ON_ERROR(rmt_tx_wait_all_done(handle->tx_channel, 50), TAG, "wait for 1-wire data transmit failed"); - - return ESP_OK; -} - -esp_err_t onewire_bus_read_bytes(onewire_bus_handle_t handle, uint8_t *rx_data, size_t rx_data_size) -{ - ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid 1-wire handle"); - ESP_RETURN_ON_FALSE(rx_data && rx_data_size != 0, ESP_ERR_INVALID_ARG, TAG, "invalid rx buffer or buffer size"); - ESP_RETURN_ON_FALSE(!(rx_data_size > handle->max_rx_bytes), ESP_ERR_INVALID_ARG, - TAG, "rx_data_size too large for buffer to hold"); - - uint8_t tx_buffer[rx_data_size]; - memset(tx_buffer, 0xFF, rx_data_size); // transmit one bits to generate read clock - - // transmit 1 bits while receiving - ESP_RETURN_ON_ERROR(rmt_receive(handle->rx_channel, handle->rx_symbols, rx_data_size * 8 * sizeof(rmt_symbol_word_t), &onewire_rmt_rx_config), - TAG, "1-wire data receive failed"); - ESP_RETURN_ON_ERROR(rmt_transmit(handle->tx_channel, handle->tx_bytes_encoder, tx_buffer, sizeof(tx_buffer), &onewire_rmt_tx_config), - TAG, "1-wire data transmit failed"); - - // wait the transmission finishes and decode data - rmt_rx_done_event_data_t rmt_rx_evt_data; - if (xQueueReceive(handle->receive_queue, &rmt_rx_evt_data, pdMS_TO_TICKS(1000)) == pdPASS) { - onewire_rmt_decode_data(rmt_rx_evt_data.received_symbols, rmt_rx_evt_data.num_symbols, rx_data); - } else { - return ESP_ERR_TIMEOUT; - } - - return ESP_OK; -} - -esp_err_t onewire_bus_write_bit(onewire_bus_handle_t handle, uint8_t tx_bit) -{ - ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid 1-wire handle"); - - const rmt_symbol_word_t *symbol_to_transmit = tx_bit ? &onewire_bit1_symbol : &onewire_bit0_symbol; - - // transmit bit - ESP_RETURN_ON_ERROR(rmt_transmit(handle->tx_channel, handle->tx_copy_encoder, symbol_to_transmit, sizeof(onewire_bit1_symbol), &onewire_rmt_tx_config), - TAG, "1-wire bit transmit failed"); - - // wait the transmission to complete - ESP_RETURN_ON_ERROR(rmt_tx_wait_all_done(handle->tx_channel, 50), TAG, "wait for 1-wire bit transmit failed"); - - return ESP_OK; -} - -esp_err_t onewire_bus_read_bit(onewire_bus_handle_t handle, uint8_t *rx_bit) -{ - ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid 1-wire handle"); - ESP_RETURN_ON_FALSE(rx_bit, ESP_ERR_INVALID_ARG, TAG, "invalid rx_bit pointer"); - - // transmit 1 bit while receiving - ESP_RETURN_ON_ERROR(rmt_receive(handle->rx_channel, handle->rx_symbols, sizeof(rmt_symbol_word_t), &onewire_rmt_rx_config), - TAG, "1-wire bit receive failed"); - ESP_RETURN_ON_ERROR(rmt_transmit(handle->tx_channel, handle->tx_copy_encoder, &onewire_bit1_symbol, sizeof(onewire_bit1_symbol), &onewire_rmt_tx_config), - TAG, "1-wire bit transmit failed"); - - // wait the transmission finishes and decode data - rmt_rx_done_event_data_t rmt_rx_evt_data; - if (xQueueReceive(handle->receive_queue, &rmt_rx_evt_data, pdMS_TO_TICKS(1000)) == pdPASS) { - uint8_t rx_buffer[1]; - onewire_rmt_decode_data(rmt_rx_evt_data.received_symbols, rmt_rx_evt_data.num_symbols, rx_buffer); - *rx_bit = rx_buffer[0] & 0x01; - } else { - return ESP_ERR_TIMEOUT; - } - - return ESP_OK; -} diff --git a/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus_rmt.h b/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus_rmt.h deleted file mode 100644 index 5661364af31..00000000000 --- a/examples/peripherals/rmt/onewire_ds18b20/components/onewire_bus/onewire_bus_rmt.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include -#include "esp_err.h" -#include "driver/gpio.h" - -/** - * @brief 1-wire bus config - * - */ -typedef struct { - gpio_num_t gpio_pin; /*!< gpio used for 1-wire bus */ - uint8_t max_rx_bytes; /*!< should be larger than the largest possible single receive size */ -} onewire_rmt_config_t; - -/** - * @brief Type of 1-wire bus handle - * - */ -typedef struct onewire_bus_t *onewire_bus_handle_t; - -/** - * @brief Install new 1-wire bus - * - * @param[in] config 1-wire bus configurations - * @param[out] handle_out Installed new 1-wire bus' handle - * @return - * - ESP_OK 1-wire bus is installed successfully. - * - ESP_ERR_INVALID_ARG Invalid argument. - * - ESP_ERR_NO_MEM Memory allocation failed. - */ -esp_err_t onewire_new_bus_rmt(onewire_rmt_config_t *config, onewire_bus_handle_t *handle_out); - -/** - * @brief Delete existing 1-wire bus - * - * @param[in] handle 1-wire bus handle to be deleted - * @return - * - ESP_OK 1-wire bus is deleted successfully. - * - ESP_ERR_INVALID_ARG Invalid argument. - */ -esp_err_t onewire_del_bus(onewire_bus_handle_t handle); - -/** - * @brief Send reset pulse on 1-wire bus, and detect if there are devices on the bus - * - * @param[in] handle 1-wire bus handle - * @return - * - ESP_OK There are devices present on 1-wire bus. - * - ESP_ERR_NOT_FOUND There is no device present on 1-wire bus. - */ -esp_err_t onewire_bus_reset(onewire_bus_handle_t handle); - -/** - * @brief Write bytes to 1-wire bus, this is a blocking function - * - * @param[in] handle 1-wire bus handle - * @param[in] tx_data pointer to data to be sent - * @param[in] tx_data_count number of data to be sent - * @return - * - ESP_OK Write bytes to 1-wire bus successfully. - * - ESP_ERR_INVALID_ARG Invalid argument. - */ -esp_err_t onewire_bus_write_bytes(onewire_bus_handle_t handle, const uint8_t *tx_data, uint8_t tx_data_size); - -/** - * @brief Read bytes from 1-wire bus - * - * @note While receiving data, we use rmt transmit channel to send 0xFF to generate read pulse, - * at the same time, receive channel is used to record weather the bus is pulled down by device. - * - * @param[in] handle 1-wire bus handle - * @param[out] rx_data pointer to received data - * @param[in] rx_data_count number of received data - * @return - * - ESP_OK Read bytes from 1-wire bus successfully. - * - ESP_ERR_INVALID_ARG Invalid argument. - */ -esp_err_t onewire_bus_read_bytes(onewire_bus_handle_t handle, uint8_t *rx_data, size_t rx_data_size); - -/** - * @brief Write a bit to 1-wire bus, this is a blocking function - * - * @param[in] handle 1-wire bus handle - * @param[in] tx_bit bit to transmit, 0 for zero bit, other for one bit - * @return - * - ESP_OK Write bit to 1-wire bus successfully. - * - ESP_ERR_INVALID_ARG Invalid argument. - */ -esp_err_t onewire_bus_write_bit(onewire_bus_handle_t handle, uint8_t tx_bit); - -/** - * @brief Read a bit from 1-wire bus - * - * @param[in] handle 1-wire bus handle - * @param[out] rx_bit received bit, 0 for zero bit, 1 for one bit - * @return - * - ESP_OK Read bit from 1-wire bus successfully. - * - ESP_ERR_INVALID_ARG Invalid argument. - */ -esp_err_t onewire_bus_read_bit(onewire_bus_handle_t handle, uint8_t *rx_bit); diff --git a/examples/peripherals/rmt/onewire_ds18b20/main/CMakeLists.txt b/examples/peripherals/rmt/onewire_ds18b20/main/CMakeLists.txt deleted file mode 100644 index 080bcfe0d19..00000000000 --- a/examples/peripherals/rmt/onewire_ds18b20/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "onewire_ds18b20_example_main.c" "ds18b20.c" - INCLUDE_DIRS ".") diff --git a/examples/peripherals/rmt/onewire_ds18b20/main/ds18b20.c b/examples/peripherals/rmt/onewire_ds18b20/main/ds18b20.c deleted file mode 100644 index 6801c4bae6c..00000000000 --- a/examples/peripherals/rmt/onewire_ds18b20/main/ds18b20.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#include -#include "ds18b20.h" -#include "esp_check.h" - -static const char *TAG = "ds18b20"; - -esp_err_t ds18b20_trigger_temperature_conversion(onewire_bus_handle_t handle, const uint8_t *rom_number) -{ - ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid 1-wire handle"); - - ESP_RETURN_ON_ERROR(onewire_bus_reset(handle), TAG, "error while resetting bus"); // reset bus and check if the device is present - - uint8_t tx_buffer[10]; - uint8_t tx_buffer_size; - - if (rom_number) { // specify rom id - tx_buffer[0] = ONEWIRE_CMD_MATCH_ROM; - tx_buffer[9] = DS18B20_CMD_CONVERT_TEMP; - memcpy(&tx_buffer[1], rom_number, 8); - tx_buffer_size = 10; - } else { // skip rom id - tx_buffer[0] = ONEWIRE_CMD_SKIP_ROM; - tx_buffer[1] = DS18B20_CMD_CONVERT_TEMP; - tx_buffer_size = 2; - } - - ESP_RETURN_ON_ERROR(onewire_bus_write_bytes(handle, tx_buffer, tx_buffer_size), - TAG, "error while triggering temperature convert"); - - return ESP_OK; -} - -esp_err_t ds18b20_get_temperature(onewire_bus_handle_t handle, const uint8_t *rom_number, float *temperature) -{ - ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid 1-wire handle"); - ESP_RETURN_ON_FALSE(temperature, ESP_ERR_INVALID_ARG, TAG, "invalid temperature pointer"); - - ESP_RETURN_ON_ERROR(onewire_bus_reset(handle), TAG, "error while resetting bus"); // reset bus and check if the device is present - - ds18b20_scratchpad_t scratchpad; - - uint8_t tx_buffer[10]; - uint8_t tx_buffer_size; - - if (rom_number) { // specify rom id - tx_buffer[0] = ONEWIRE_CMD_MATCH_ROM; - tx_buffer[9] = DS18B20_CMD_READ_SCRATCHPAD; - memcpy(&tx_buffer[1], rom_number, 8); - tx_buffer_size = 10; - } else { - tx_buffer[0] = ONEWIRE_CMD_SKIP_ROM; - tx_buffer[1] = DS18B20_CMD_READ_SCRATCHPAD; - tx_buffer_size = 2; - } - - ESP_RETURN_ON_ERROR(onewire_bus_write_bytes(handle, tx_buffer, tx_buffer_size), - TAG, "error while sending read scratchpad command"); - ESP_RETURN_ON_ERROR(onewire_bus_read_bytes(handle, (uint8_t *)&scratchpad, sizeof(scratchpad)), - TAG, "error while reading scratchpad command"); - - ESP_RETURN_ON_FALSE(onewire_check_crc8((uint8_t *)&scratchpad, 8) == scratchpad.crc_value, ESP_ERR_INVALID_CRC, - TAG, "crc error"); - - static const uint8_t lsb_mask[4] = { 0x07, 0x03, 0x01, 0x00 }; - uint8_t lsb_masked = scratchpad.temp_lsb & (~lsb_mask[scratchpad.configuration >> 5]); // mask bits not used in low resolution - *temperature = (((int16_t)scratchpad.temp_msb << 8) | lsb_masked) / 16.0f; - - return ESP_OK; -} - -esp_err_t ds18b20_set_resolution(onewire_bus_handle_t handle, const uint8_t *rom_number, ds18b20_resolution_t resolution) -{ - ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid 1-wire handle"); - - ESP_RETURN_ON_ERROR(onewire_bus_reset(handle), TAG, "error while resetting bus"); // reset bus and check if the device is present - - uint8_t tx_buffer[10]; - uint8_t tx_buffer_size; - - if (rom_number) { // specify rom id - tx_buffer[0] = ONEWIRE_CMD_MATCH_ROM; - tx_buffer[9] = DS18B20_CMD_WRITE_SCRATCHPAD; - memcpy(&tx_buffer[1], rom_number, 8); - tx_buffer_size = 10; - } else { - tx_buffer[0] = ONEWIRE_CMD_SKIP_ROM; - tx_buffer[1] = DS18B20_CMD_WRITE_SCRATCHPAD; - tx_buffer_size = 2; - } - - ESP_RETURN_ON_ERROR(onewire_bus_write_bytes(handle, tx_buffer, tx_buffer_size), - TAG, "error while sending read scratchpad command"); - - tx_buffer[0] = 0; - tx_buffer[1] = 0; - tx_buffer[2] = resolution; - ESP_RETURN_ON_ERROR(onewire_bus_write_bytes(handle, tx_buffer, 3), - TAG, "error while sending write scratchpad command"); - - return ESP_OK; -} diff --git a/examples/peripherals/rmt/onewire_ds18b20/main/ds18b20.h b/examples/peripherals/rmt/onewire_ds18b20/main/ds18b20.h deleted file mode 100644 index 7c106461e7b..00000000000 --- a/examples/peripherals/rmt/onewire_ds18b20/main/ds18b20.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#pragma once - -#include "onewire_bus.h" - -#define DS18B20_CMD_CONVERT_TEMP 0x44 -#define DS18B20_CMD_WRITE_SCRATCHPAD 0x4E -#define DS18B20_CMD_READ_SCRATCHPAD 0xBE - -/** - * @brief Structure of DS18B20's scratchpad - * - */ -typedef struct { - uint8_t temp_lsb; /*!< lsb of temperature */ - uint8_t temp_msb; /*!< msb of temperature */ - uint8_t th_user1; /*!< th register or user byte 1 */ - uint8_t tl_user2; /*!< tl register or user byte 2 */ - uint8_t configuration; /*!< configuration register */ - uint8_t _reserved1; - uint8_t _reserved2; - uint8_t _reserved3; - uint8_t crc_value; /*!< crc value of scratchpad data */ -} ds18b20_scratchpad_t; - -/** - * @brief Enumeration of DS18B20's resolution config - * - */ -typedef enum { - DS18B20_RESOLUTION_12B = 0x7F, /*!< 750ms convert time */ - DS18B20_RESOLUTION_11B = 0x5F, /*!< 375ms convert time */ - DS18B20_RESOLUTION_10B = 0x3F, /*!< 187.5ms convert time */ - DS18B20_RESOLUTION_9B = 0x1F, /*!< 93.75ms convert time */ -} ds18b20_resolution_t; - -/** - * @brief Trigger temperature conversion of DS18B20 - * - * @param[in] handle 1-wire handle with DS18B20 on - * @param[in] rom_number ROM number to specify which DS18B20 to send command, NULL to skip ROM - * @return - * - ESP_OK Trigger tempreture convertsion success. - * - ESP_ERR_INVALID_ARG Invalid argument. - * - ESP_ERR_NOT_FOUND There is no device present on 1-wire bus. - */ -esp_err_t ds18b20_trigger_temperature_conversion(onewire_bus_handle_t handle, const uint8_t *rom_number); - -/** - * @brief Get temperature from DS18B20 - * - * @param[in] handle 1-wire handle with DS18B20 on - * @param[in] rom_number ROM number to specify which DS18B20 to read from, NULL to skip ROM - * @param[out] temperature result from DS18B20 - * @return - * - ESP_OK Get tempreture from DS18B20 success. - * - ESP_ERR_INVALID_ARG Invalid argument. - * - ESP_ERR_NOT_FOUND There is no device present on 1-wire bus. - * - ESP_ERR_INVALID_CRC CRC check failed. - */ -esp_err_t ds18b20_get_temperature(onewire_bus_handle_t handle, const uint8_t *rom_number, float *temperature); - -/** - * @brief Set DS18B20's temperation conversion resolution - * - * @param[in] handle 1-wire handle with DS18B20 on - * @param[in] rom_number ROM number to specify which DS18B20 to read from, NULL to skip ROM - * @param[in] resolution resolution of DS18B20's temperation conversion - * @return - * - ESP_OK Set DS18B20 resolution success. - * - ESP_ERR_INVALID_ARG Invalid argument. - * - ESP_ERR_NOT_FOUND There is no device present on 1-wire bus. - */ -esp_err_t ds18b20_set_resolution(onewire_bus_handle_t handle, const uint8_t *rom_number, ds18b20_resolution_t resolution); diff --git a/examples/peripherals/rmt/onewire_ds18b20/main/onewire_ds18b20_example_main.c b/examples/peripherals/rmt/onewire_ds18b20/main/onewire_ds18b20_example_main.c deleted file mode 100644 index ef723bf2be8..00000000000 --- a/examples/peripherals/rmt/onewire_ds18b20/main/onewire_ds18b20_example_main.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#include "esp_log.h" -#include "esp_check.h" - -#include "onewire_bus.h" -#include "ds18b20.h" - -static const char *TAG = "example"; - -#define EXAMPLE_ONEWIRE_GPIO_PIN GPIO_NUM_5 -#define EXAMPLE_ONEWIRE_MAX_DEVICES 5 - -void app_main(void) -{ - onewire_rmt_config_t config = { - .gpio_pin = EXAMPLE_ONEWIRE_GPIO_PIN, - .max_rx_bytes = 10, // 10 tx bytes(1byte ROM command + 8byte ROM number + 1byte device command) - }; - - // install new 1-wire bus - onewire_bus_handle_t handle; - ESP_ERROR_CHECK(onewire_new_bus_rmt(&config, &handle)); - ESP_LOGI(TAG, "1-wire bus installed"); - - // create 1-wire rom search context - onewire_rom_search_context_handler_t context_handler; - ESP_ERROR_CHECK(onewire_rom_search_context_create(handle, &context_handler)); - - uint8_t device_num = 0; - uint8_t device_rom_id[EXAMPLE_ONEWIRE_MAX_DEVICES][8]; - - // search for devices on the bus - do { - esp_err_t search_result = onewire_rom_search(context_handler); - - if (search_result == ESP_ERR_INVALID_CRC) { - continue; // continue on crc error - } else if (search_result == ESP_FAIL || search_result == ESP_ERR_NOT_FOUND) { - break; // break on finish or no device - } - - ESP_ERROR_CHECK(onewire_rom_get_number(context_handler, device_rom_id[device_num])); - ESP_LOGI(TAG, "found device with rom id " ONEWIRE_ROM_ID_STR, ONEWIRE_ROM_ID(device_rom_id[device_num])); - device_num ++; - } while (device_num < EXAMPLE_ONEWIRE_MAX_DEVICES); - - // delete 1-wire rom search context - ESP_ERROR_CHECK(onewire_rom_search_context_delete(context_handler)); - ESP_LOGI(TAG, "%d device%s found on 1-wire bus", device_num, device_num > 1 ? "s" : ""); - - // convert and read temperature - while (device_num > 0) { - esp_err_t err; - vTaskDelay(pdMS_TO_TICKS(200)); - - // set all sensors' temperature conversion resolution - err = ds18b20_set_resolution(handle, NULL, DS18B20_RESOLUTION_12B); - if (err != ESP_OK) { - continue; - } - - // trigger all sensors to start temperature conversion - err = ds18b20_trigger_temperature_conversion(handle, NULL); // skip rom to send command to all devices on the bus - if (err != ESP_OK) { - continue; - } - - vTaskDelay(pdMS_TO_TICKS(800)); // 12-bit resolution needs 750ms to convert - - // get temperature from sensors - for (uint8_t i = 0; i < device_num; i ++) { - float temperature; - err = ds18b20_get_temperature(handle, device_rom_id[i], &temperature); // read scratchpad and get temperature - if (err != ESP_OK) { - continue; - } - ESP_LOGI(TAG, "temperature of device " ONEWIRE_ROM_ID_STR ": %.2fC", ONEWIRE_ROM_ID(device_rom_id[i]), temperature); - } - } - - ESP_ERROR_CHECK(onewire_del_bus(handle)); - ESP_LOGI(TAG, "1-wire bus deleted"); -}