Compare commits

..

125 Commits

Author SHA1 Message Date
5d9b98c9b0 IDF master cf457d412 (#5073)
esp-dsp: master 7cc5073
esp-face: master 420fc7e
esp-rainmaker: f1b82c7
esp32-camera: master 2dded7c
esp_littlefs: master d268e18
2021-04-17 15:28:16 +03:00
11f89cddf6 WiFiClientSecure fix flipped cert/key in comment (#5065) 2021-04-17 02:07:41 +03:00
01c8cae0dc Added method to change the ledc PWM frequency programmatically (#5003)
Added method to change the ledc PWM frequence programmatically
Returning frequency from ledcChangeFrequency
2021-04-17 02:06:58 +03:00
57cf2fb9f5 Fix possible string overflow in BTAdvertisedDeviceSet::toString() 2021-04-16 18:51:01 +03:00
41c372c143 [2.0.0] BtClassic Discovery with info without connect (#4811)
Hey guys,
so I wanted to do a BtClassic Discovery without the need to call connect
and to list all found devices on a display and continue work with that list.

I wasn't capable to test the example code with my file structure, but I did use the discovery already in some different situations.

However when I noted that the Bluedroid stack won't let me enforce an RfComm SPP connection to a GPS Device (Skytraxx 2 plus, I guess its interface is built so simple that it doesn't advertise its SPP over SDP), I will probably have to switch to BtStack (BlueKitchen) and stop on this side meanwhile
2021-04-16 01:37:33 +03:00
223acb3511 C3 toolchain uses github as source 2021-04-16 00:50:27 +03:00
f6c9faf4da [2.0.0] FS::name() returns the item name as in Arduino SD (#4892)
* FS::name() returns the item name as in Arduino SD

Added method FS::path() that returns the full path

* Adjust examples
2021-04-15 17:25:01 +03:00
89e7893b1a [2.0.0] Add BLE characteristic callbacks overloads (#4832)
Add BLE characteristic callbacks overloads with esp_ble_gatts_cb_param_t* param.
Example:

class BleCharactCallback : public BLECharacteristicCallbacks
{
    void onRead(BLECharacteristic *pCharacteristic, esp_ble_gatts_cb_param_t *param)
    {
        auto addr = param->read.bda;
        ESP_LOGV(TAG, "Device " ESP_BD_ADDR_STR " request data", ESP_BD_ADDR_HEX(addr));
    }
    void onWrite(BLECharacteristic *pCharacteristic, esp_ble_gatts_cb_param_t *param)
    {
        auto addr = param->write.bda;
        ESP_LOGV(TAG, "Device " ESP_BD_ADDR_STR " transmit data", ESP_BD_ADDR_HEX(addr));
    }
};
2021-04-15 16:08:22 +03:00
7a4e7066f9 Add setMTU function to BLEClient.cpp/.h (#4999)
The current implementation has a getMTU function which returns the mtu sent in a message.

This function allows you to set the MTU value on the connected device, it first sets the MTU locally by calling esp_ble_gatt_set_local_mtu. It then calls esp_ble_gattc_send_mtu_req to have the connected device also change its MTU size.
2021-04-15 16:07:45 +03:00
f3dca15a6f Fix TTGO Boards missing upload parameters,add Twatch revision (#5063) 2021-04-15 14:32:39 +03:00
9f1330c70c esp32s2 temp sensor (#5044) 2021-04-15 14:32:03 +03:00
ec7aeb4903 Removed ProS2 and added TinyS2 to boards.txt (#5037) 2021-04-15 14:31:41 +03:00
9a518cd3d7 LITTLEFS update - partition label and multiple partitions, idea copied from SPIFFS (#5023)
Note, maxOpenFiles parameter is unused but kept for compatibility.
2021-04-15 14:31:01 +03:00
81b7c47203 Serial::end hang (#5047)
workaround for #5043. There is a timing issue with HardwareSerial::end. I'm not sure what is hung, but it should be possible to see this in jtag, as it does cause a reboot if you let it. The delay needs to be before you detach the device!?
2021-04-15 12:46:53 +03:00
e6ba8c7ac9 Add KSZ8081 support. (#5061)
This adds support for the KSZ8081 ethernet phy.
Only the IDF 4+ specific code is modified, as the phy support was only
added recently:
espressif/esp-idf@aecfbf96
2021-04-15 12:43:29 +03:00
72eb3f32fe Add Adafruit esp32s2 boards with custom bootloader, partition and upload.extra_flags (#5056)
done on behalf of @ladyada, this PR does:

Add Adafruit FunHouse and upcoming Adafruit Feather Esp32s2
Update Adafruit magtag and metro esp32s2 to have tinyuf2 as factory app
Also modify platform.txt as discussed in adafruit#2 + adafruit#3 + adafruit#4 to add support for
Board/variant partition.csv, bootloader.bin ( priority is user sketch > variant > build.parition/boot )
upload.extra_flags to optionally flash tinyuf2 as factory application
Remove duplicated parameter in running python script in linux and windows
Please review and let me know if you want any changes.

Notes: tinyuf2 is a uf2 bootloader for multiple platforms. For esp32s2, it is an factory app to perform uf2 firmware update.
2021-04-15 12:41:59 +03:00
66b11ff2a4 Update platformio-build-esp32c3.py 2021-04-14 18:18:48 +03:00
404a31f445 Initial Esp32c3 Support (#5060) 2021-04-14 18:10:05 +03:00
371f382db7 Fix Serial RX and add option for FIFO Full Threshold in Serial.begin
Fixes: https://github.com/espressif/arduino-esp32/issues/5005
2021-04-08 15:29:53 +03:00
425619dfea Fix upload over USB CDC (USB serial must be set to 0) 2021-04-05 20:24:46 +03:00
aeb4a13aad ESP32S2 pinmap (#5015) 2021-04-05 16:54:40 +03:00
8645971981 Fix delayMicroseconds() to use 64bit period
fixes: https://github.com/espressif/arduino-esp32/issues/5000
2021-04-05 15:15:09 +03:00
5502879a5b v2.0.0 Add support for ESP32S2 and update ESP-IDF to 4.4 (#4996)
This is very much still work in progress and much more will change before the final 2.0.0

Some APIs have changed. New libraries have been added. LittleFS included.

Co-authored-by: Seon Rozenblum <seonr@3sprockets.com>
Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
Co-authored-by: geeksville <kevinh@geeksville.com>
Co-authored-by: Mike Dunston <m_dunston@comcast.net>
Co-authored-by: Unexpected Maker <seon@unexpectedmaker.com>
Co-authored-by: Seon Rozenblum <seonr@3sprockets.com>
Co-authored-by: microDev <70126934+microDev1@users.noreply.github.com>
Co-authored-by: tobozo <tobozo@users.noreply.github.com>
Co-authored-by: bobobo1618 <bobobo1618@users.noreply.github.com>
Co-authored-by: lorol <lorolouis@gmail.com>
Co-authored-by: geeksville <kevinh@geeksville.com>
Co-authored-by: Limor "Ladyada" Fried <limor@ladyada.net>
Co-authored-by: Sweety <switi.mhaiske@espressif.com>
Co-authored-by: Loick MAHIEUX <loick111@gmail.com>
Co-authored-by: Larry Bernstone <lbernstone@gmail.com>
Co-authored-by: Valerii Koval <valeros@users.noreply.github.com>
Co-authored-by: 快乐的我531 <2302004040@qq.com>
Co-authored-by: chegewara <imperiaonline4@gmail.com>
Co-authored-by: Clemens Kirchgatterer <clemens@1541.org>
Co-authored-by: Aron Rubin <aronrubin@gmail.com>
Co-authored-by: Pete Lewis <601236+lewispg228@users.noreply.github.com>
2021-04-05 14:23:58 +03:00
46d5afb17f Quote {build.source.path} to allow spaces in path (#4868)
Previously sketches or examples that had spaces anywhere in their absolute
path caused a total build failure. By adding quotes around the path in
platform.txt, they now build correctly

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2021-03-26 13:24:21 +02:00
66746750a4 IDF release/v3.3.5 85c43024c (#4976)
esp-face: master 420fc7e
esp32-camera: master 488c308
2021-03-26 12:56:06 +02:00
e7a2759b65 Allow STA SSID length of 32
Fixes: https://github.com/espressif/arduino-esp32/issues/3218
2021-03-23 14:30:19 +02:00
2ee66b54f0 IDF release/v3.3 c43efe150 (#4936)
esp-face: master 420fc7e
esp32-camera: master 488c308
FreeRTOS Static
2021-03-20 14:04:35 +02:00
2d3c57635d Fix: WebServer: Digest authentication failed for some clients
Ports: 4d3850e87e
2021-03-19 02:10:16 +02:00
a299ddc99e Change send_ssl_data to use size_t instead of uint16_t
Fixes: https://github.com/espressif/arduino-esp32/issues/4960
2021-03-18 15:02:37 +02:00
93bcf5f250 Allow passing custom HTTPClient to HTTPUpdate (#4959)
This enables customizing HTTP headers which adds some extra flexibility.
This does not break anything of course because this change introduces a new constructor with a new additional HTTPClient argument for HTTPUpdate class.
2021-03-18 13:12:57 +02:00
bd41334265 Fix ETH not enabling DHCP when configured with INADDR_NONE
Fixes: https://github.com/espressif/arduino-esp32/issues/4778
2021-03-18 00:53:53 +02:00
9a0762ad2a [BLE Client] Fix Deadlock when calling writeValue after registerForNotify
Fixes: https://github.com/espressif/arduino-esp32/issues/4952
2021-03-17 18:46:55 +02:00
a451c9ef0d Fix HTTPClient crash on GET() for url with redirects
Fixes: https://github.com/espressif/arduino-esp32/issues/4931
2021-03-16 21:28:19 +02:00
d362e1ee1a [BLE] Allows you to specify which channels are used to advertise. (#4954)
In some use cases getting rssi signal from one channel is more stable (less variance) than rssi from the three advertising channels.

This change allows you to specify which channels are used to advertise.
2021-03-16 11:56:23 +02:00
33d9f4aa19 Update GitHub Pages Builder
Add some debug and allow building from a branch named `pages`
2021-03-16 02:48:17 +02:00
63c51d51fb Update HTTPUpdate.cpp (#4942)
This is a mirror of a change in esp8266 needed to update with a url that redirects.
2021-03-16 02:14:53 +02:00
5b845272ed Fix BluetoothSerial TX Stall
Fixes: https://github.com/espressif/arduino-esp32/issues/4949
2021-03-16 02:11:59 +02:00
5da4a47bdf Update debian_ubuntu.md (#4907)
* Update debian_ubuntu.md

ERROR: This script does not work on Python 2.7 The minimum supported Python version is 3.6. Please use https://bootstrap.pypa.io/2.7/get-pip.py instead.

* Update debian_ubuntu.md

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2021-03-15 13:22:34 +02:00
3253de8792 added scan_method = WIFI_ALL_CHANNEL_SCAN into wifi config in WiFi.begin() to let the scan choose the nearest / strongest AP in case that there are multiple APs with the same SSID (#4947)
In case you have multiple APs with the same SSID/password and WiFi.begin(ssid, pwd) is called, ESP32 defaults to connect to THE FIRST AP FOUND matching ssid - according to:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html#_CPPv418wifi_scan_method_t

This can cause situations that ESP32 is trying to connect to AP which is far away from it (weak signal) even there is AP close to it, just as in my house - I have AP on channel 6 which is in the 1st floor (quite far from room where I do the programming) and AP on channel 13 in the same room I do the programming (which is in the 2nd floor) - result: ESP32 is trying to connect to the AP on channel 6 because it finds it first and never try the AP on channel 13 in the same room, result of this is very unreliable WiFi connection.

When scan_method is set to WIFI_ALL_CHANNEL_SCAN, ESP32 scans all channels and choose the nearest / strongest AP (matching the ssid of course) as expected - result is no connection problems at all.

Therefore I propose adding this parameter into WiFi.begin, connection problems as described above are quite confusing (especially for beginners), I can imagine that for example Schools there are usually using mutliple APs and this can cause intermittent connection problems without obvious reason.
2021-03-15 13:21:43 +02:00
a31f30529d fix spiTransferBytesNL() writes past end of data_out
Fixes: https://github.com/espressif/arduino-esp32/issues/4935
2021-03-15 10:40:50 +02:00
35643bdd9b adds esp8266-style hostname setting (#4938)
a little step to make esp8266 code compile without changes under esp32
2021-03-15 10:10:30 +02:00
8dc70e0add Revert "Update licenses"
This reverts commit 4b3f5c8ed4.
2021-03-11 12:11:53 +02:00
b42739dfa4 Update howsmyssl.com root certificate 2021-03-10 17:55:40 +02:00
93d5b8c672 Fix String::replace()
Fixes: https://github.com/espressif/arduino-esp32/issues/4920
2021-03-10 17:13:14 +02:00
f815a7c636 Add WiFi.softAPSSID()
Fixes: https://github.com/espressif/arduino-esp32/issues/4922
2021-03-10 16:36:51 +02:00
23f6e81d52 Fix AsyncUDP reporting bad address and port
Fixes: https://github.com/espressif/arduino-esp32/issues/4923
2021-03-10 16:20:18 +02:00
e8311b00ae IDF release/v3.3 0bfff0b25 (#4895)
esp-face: master 420fc7e
esp32-camera: master 770f26a
2021-03-10 14:48:35 +02:00
4d95e3a7ea Fix BT not starting correctly and SPP Coex not working
Fixes: https://github.com/espressif/arduino-esp32/issues/4912
2021-03-09 01:56:47 +02:00
7dc769d81c Board name change (ETBoard -> ET-Board) (#4858)
Co-authored-by: ketri-kjy <jinyoung@ketri.re.kr>
Co-authored-by: ketri2484 <ketri2484@gamil.com>
Co-authored-by: me-no-dev <hristo@espressif.com>
2021-03-09 00:32:02 +02:00
4204d1e60a Handle PSRAM libs in PlatformIO build script (#4911)
This PR adds PSRAM-specific libraries to the final linker command depending on the `BOARD_HAS_PSRAM` macro.

cc @me-no-dev
2021-03-09 00:21:52 +02:00
d7fda910fb Update stale.yml (#4902)
Labels names updated. Not sure if the spaces in label's names are going to work.
2021-03-06 14:15:46 +02:00
f7fc8ab377 Use HTTP method table from ESP-IDF's nghttp (#4900)
Fixes: #4884

* Use HTTP method table from ESP-IDF's nghttp
* Parse methods using IDF's HTTP method list
* Make example's loops to allow the CPU to switch tasks
2021-03-05 13:40:52 +02:00
dd834b3372 Ensure that String::setLen() is always after any memory operation
Since `String::setLen()` is now modifying the buffer, this change is required to ensure that the proper buffer is changed.
2021-03-05 12:00:39 +02:00
0e55f775d3 Fixing issue in String::remove 2021-03-04 22:41:46 +02:00
22a488cf23 Fix String::clear() not clearing the string properly
Fixes: https://github.com/espressif/arduino-esp32/issues/4893
2021-03-04 21:20:27 +02:00
6e7cc5210d Update pins_arduino.h for FireBettle-ESP32 (#4867)
* Update pins_arduino.h

Fix the bug that the IDE show: "Error compiling for the board FireBettle-ESP32" 
Detial"error : redefinition of const uint8_t D0~D9"

* Update pins_arduino.h

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2021-03-04 17:04:18 +02:00
7a6900a1f2 Correct issue 4871 - change space to underscore in boards.txt setting lolin32-lite.build.board (#4885) 2021-03-04 15:31:23 +02:00
0e0a7565e8 Remove tools/sdk/include/nimble from include path (#4891) 2021-03-04 15:30:34 +02:00
bd3addeb8e Fixed use of Bluedroid instead of BT in HAL. (#4879)
Fixed use of CONFIG_BLUEDROID_ENABLED instead of CONFIG_BT_ENABLED in HAL. This prevented compilation with Nimble-only configuration without apparent benefit.
2021-03-01 23:55:04 +02:00
1cf1c8eb79 Fix several SD card issues (#4876)
- File might not eval to false if opened with write/append and SD is gone
- Allow card to be formatted if FAT partition was not found
- Mark card as gone in certain situations
- Fix several logic errors in low level SD API
2021-03-01 23:52:57 +02:00
3fe7c2e8cd Add div by zero check back into WMath::map (#4853)
* Add div by zero check back into WMath::map
* include esp32-hal-log.h

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2021-02-24 19:04:36 +02:00
5d00b6eb16 Fix case where EEPROM will try to return longer string than it should
Fixes: https://github.com/espressif/arduino-esp32/issues/4768
2021-02-24 18:47:11 +02:00
419ba32432 etboard pinmap upload (#4748)
Co-authored-by: ketri-kjy <jinyoung@ketri.re.kr>
Co-authored-by: ketri2484 <ketri2484@gamil.com>
2021-02-23 09:49:38 +02:00
a0ddd8a16e IDF release/v3.3 7a85334d8 (#4813)
esp-face: master 420fc7e
esp32-camera: master a5ccbec
2021-02-23 01:06:41 +02:00
b8dab5ed1a Added possibility to use ESP32-IDF log insted of redefined one (#4845)
With this PR user can select to use the original ESP-IDF log instead of the redefined one.

User can also redefine the log function as per [Logging Library](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/log.html#_CPPv419esp_log_set_vprintf14vprintf_like_t) so he can for example redirect logs to a file.

To enable this change just add -DUSE_ESP32_LOG to build flags.
User can also change the default TAG (that now is ES32) to whatever it wants adding '-DTAG="tag_value"' to build flags
2021-02-23 00:18:15 +02:00
2141313148 Fix PSRAM support (#4850) 2021-02-23 00:15:48 +02:00
44aaf13225 Added BLEAddress operator overload methods (#4839)
Allows BLEAddress to be used as key in std::map etc
2021-02-22 19:37:07 +02:00
560c0f45f5 Fix dropped SSL connection when buffer gets full. (#4820)
mbedTLS requires repeated calls to mbedtls_ssl_write() whenever it returns MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE. this happens when the client sends data faster then the server or the connection can handle.
2021-02-22 19:34:56 +02:00
4b3f5c8ed4 Update licenses 2021-02-18 12:14:35 +02:00
c282cd8f5f Remove temp buffer in WiFiClientSecure::lastError (#4822)
The temp buffer serves no purpose here. Also mbedtls_strerror can be called with size == 0 safely.
2021-02-18 11:44:44 +02:00
7e59971d2f Add Lolin32 Lite and TTGO T7 boards (#4819)
Add the Wemos Lolin32 Lite (no longer being produced same as Lolin32) and
the TTGO T7 v1.3 and v1.4 boards (status unknown). All three are rather
generic ESP32 boards the main difference being pin layouts.
2021-02-18 11:43:11 +02:00
f4b17b3033 Allow releases from different branches 2021-02-17 14:06:30 +02:00
1ab550f6f2 Changed BLE notify_callback from raw function pointer to std::function (#4737) 2021-02-16 22:10:04 +02:00
9be784f69b Improve cleanup in BLEClient (#4742)
- Remove client from the list of devices in case registration fails
- Filter other events not related to registration during registration phase
- Cleanup if connect fails
- Reset if after disconnect
- Disconnect callback *after* cleanup is done so object can be deleted

This fixes some of the issues I had like:
- `BLEClient::connect` hangs up and never recovered because registration failed
- `BLEClient` could not be deleted after disconnect or deletion creating ghost events https://github.com/espressif/arduino-esp32/issues/4047
- `BLEClient` could not be properly reused after a connection was attempted (successful or not) 

* Cleanup in case of registration and connect failure.
Cleanup before calling disconnect callback for safe delete.
Reject other events during registration.
Adresses #4047, #4055

* Clear if after unregister #4047
2021-02-16 11:21:45 +02:00
7cdfb8bc7c Refactor BLEAdvertisedDevice (#4739)
fixes #4596

* Prevent possible undefined behaviour by get methods not taking an index as parameter
* Add methods to get the count of service data UUIDs and service UUIDs
* Various code improvements
2021-02-16 11:02:58 +02:00
8134a42162 Fix leak of memory and possible crashes in AsyncUDP 2021-02-16 10:26:37 +02:00
f13ff65691 AsyncUDP: Added lastErr helper variable (#4789)
The variable is useful when debugging AsyncUDP send problems.
The upper application can read and analyze the error reason.
2021-02-16 02:21:53 +02:00
e831680a41 Fixed a memory leak in BLE (issue #4753) (#4761)
* Fixed crash on delete after disconnect

* Fixed memory leak when getting characteristics

* Removed guard

Co-authored-by: ushiboy <ushiboy.dev@gmail.com>
2021-02-16 01:50:24 +02:00
d964873840 Added more inclusive CORS policy (#4767) 2021-02-16 01:49:30 +02:00
7e8993fc83 Speed up upload by a factor of 17 (#4787)
* Speed up upload by a factor of 17

Uploads are very slow because of an unnecessary "client.connected()" check in _uploadReadByte().

Here is what happens:
client.connected() is called for every byte read.  WiFiClient::connected() calls recv(fd(), &dummy, 0, MSG_DONTWAIT); which takes a relatively long time, so the optimized path of returning a buffered byte via client.read() is effectively nullified.

Removing the one line changed the upload speed for a 2 MB file (discarding the received data) from 22 KB/sec (before) to 367 KB/sec (after).

The change is safe in the face of disconnects because client.read(), when it no longer has buffered data, calls (WiFiClient)  fillBuffer(), which calls recv(), so the disconnection will be detected in due course.

* Move disconnect check into the timeout loop
2021-02-16 01:47:01 +02:00
15bae92a72 Idf release/v3.3 d8082b7f3
* Update IDF to d8082b7f3
2021-02-16 01:37:37 +02:00
6f23cd5988 Make sure that HTTPClient disconnects from the old server if redirecting to new one
Fixes: https://github.com/espressif/arduino-esp32/issues/4763
2021-02-04 02:42:44 +02:00
ad4cf1461b Rework setHostname for WiFi STA
Fixes: https://github.com/espressif/arduino-esp32/issues/2537
2021-02-03 13:17:49 +02:00
5de03a3918 Fix WiFi STA config IP to INADDR_NONE results in 255.255.255.255
Fixes: https://github.com/espressif/arduino-esp32/issues/4732
2021-02-03 11:47:35 +02:00
4b385690bc Move default Arduino partitions to a separate section (#4747) 2021-01-27 13:52:39 +02:00
dd513df124 Add arm64 support for mkspiffs 2021-01-21 14:42:31 +02:00
cee659563d IDF release/v3.3 7e63061fa (#4726)
Co-authored-by: me-no-dev <me-no-dev@github.com>
2021-01-21 14:33:55 +02:00
55442a05a4 Remove an unused variable 'channel' (#4725) 2021-01-21 14:31:25 +02:00
c9b3e512dd Make BLERemoteCharacteristic::getRemoteService() public #3367 (#4735) 2021-01-21 14:30:33 +02:00
8d0e68db4f Added parameter to Preferences::begin to select non-default NVS partition (#4718) 2021-01-15 19:06:51 +02:00
d2530850a3 Copy platformio-build.py in the release package 2021-01-14 11:17:21 +02:00
7ecbb483da Update toolchain and move files to github 2021-01-12 17:53:49 +02:00
b0e896e9ae IDF release/v3.3 cd59d107b (#4708)
Co-authored-by: me-no-dev <me-no-dev@github.com>
2021-01-12 15:24:34 +02:00
08f4665775 Change fetch depth for release so that history can be fetched 2021-01-12 15:09:28 +02:00
2452c1fb53 IDF release/v3.3 71df1f742
esp-face: master 420fc7e
esp32-camera: master 0107093
2021-01-11 14:20:02 +02:00
5f98370707 Add IP101 support (#4620) 2021-01-11 12:00:35 +02:00
81b9130d8d BluetoothSerial SSP Authentication with callbacks (#4634)
Added authentication callbacks and example, resolves #4622.
2021-01-11 11:58:15 +02:00
434d02c49f BLERemoteCharacteristic::registerForNotify: Permit event registration without updating descriptor. (#4659) 2021-01-11 11:44:38 +02:00
15db297130 availableForWrite (#4664)
added availableForWrite to Print.h to make compatible with Arduino Print.h
2021-01-11 11:43:10 +02:00
fe093a5e35 Sanitize compiler warning in BLERemoteService.cpp (issue #4660) (#4669)
Compiler complains on unused parameter pCharacteristicMap:

framework-arduinoespressif32\libraries\BLE\src\BLERemoteService.cpp: In member function 'void BLERemoteService::getCharacteristics(std::map<short unsigned int, BLERemoteCharacteristic*>*)':
\framework-arduinoespressif32\libraries\BLE\src\BLERemoteService.cpp:246:89: warning: parameter 'pCharacteristicMap' set but not used [-Wunused-but-set-parameter]
 void BLERemoteService::getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* pCharacteristicMap) {
2021-01-11 11:42:32 +02:00
a0ef17a9dd Use non-deprecated DPORT values in SPI HAL (#4682) 2021-01-11 11:40:18 +02:00
be77bd4e27 Resolve crash with timer interrupt functions called from ISR (#4684) 2021-01-11 11:39:39 +02:00
ef99cd7fe7 Add WiFiClientSecure::setInsecure() to equalize API with ESP8266 (#4648) 2020-12-21 01:09:37 +02:00
b05bdf6904 Update esptool for Big Sur 2020-12-07 10:19:55 +02:00
442c63a4c6 IDF release/v3.3 b4c075169 (#4604)
esp-face: master 420fc7e
esp32-camera: master 0107093
2020-12-07 10:03:16 +02:00
d1a4b3b822 Add loop task stack size config to Kconfig
Follow up for https://github.com/espressif/arduino-esp32/pull/4564
2020-12-02 11:56:45 +02:00
7d5bf9e385 [1.0.5] Make looptask stack size configurable (#4564)
Added guarded define to set the stacksize on the main looptask.
Advantage of this is that build_flags can be used to provide a different value for the stack size should it be neccessary
default behaviour is unaffected
2020-12-02 11:52:04 +02:00
aac26a4d1e [1.0.5] Update Heltec ESP32 series boards definition (#4577) 2020-12-02 11:50:12 +02:00
804c221499 Update .gitignore 2020-12-01 22:20:06 +02:00
3236358ded Update WiFiClient.cpp (#4573)
Replace (depricated) bzero, bcopy with memset and memcpy.
2020-12-01 16:35:12 +02:00
82e71f9b50 Update ssl_client.cpp (#4574)
Replace (depricated) bzero with memset.
2020-12-01 16:34:36 +02:00
2e12392721 IDF release/v3.3 c33fc7821
esp-face: master 420fc7e
esp32-camera: master 0107093
2020-12-01 16:22:18 +02:00
6b0114366b Fix logic in SPIClass::setHwCs. (#4559)
Fixes #4558
2020-11-23 14:22:43 +02:00
18832bb418 M5TimerCam: add LED_BUILTIN & SS/MOSI/MISO/SCK (#4560) 2020-11-23 14:21:58 +02:00
97dcea2b99 Update library.properties (#4563)
Set the category to silence this warning in the Arduino IDE:
```
WARNING: Category '' in library WiFiProv is not valid. Setting to 'Uncategorized'
```
2020-11-23 14:21:34 +02:00
dcff2e9774 Separate Provisioning library from WiFi library (#4547) 2020-11-19 00:12:16 +02:00
6d256b6454 IDF release/v3.3 68b237fe5 with Disable IRAM optimisation for WiFi 2020-11-16 13:06:50 +02:00
f6bf0f7aa2 IDF release/v3.3 68b237fe5 2020-11-16 12:44:07 +02:00
a59eb5d51e Merge branch 'master' into idf-release/v3.3 2020-11-16 12:09:23 +02:00
cee7b4237c Merge branch 'master' into idf-release/v3.3 2020-11-15 12:02:51 +02:00
954df2fc3e Disable IRAM optimization for WiFi 2020-11-15 11:56:01 +02:00
cecef8e930 IDF release/v3.3 68b237fe5 2020-11-14 00:33:27 +00:00
a8e99baeab Merge branch 'master' into idf-release/v3.3 2020-11-12 21:29:57 +02:00
7494c4e76d IDF release/v3.3 44ec7972b 2020-11-08 00:36:32 +00:00
c1951670d1 IDF release/v3.3 66d3783c8 2020-11-06 18:15:23 +00:00
3667 changed files with 450116 additions and 15616 deletions

View File

@ -98,8 +98,8 @@ function build_sketch(){ # build_sketch <fqbn> <path-to-ino> [extra-options]
win_opts="-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version -prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version"
fi
echo ""
echo "Compiling '"$(basename "$sketch")"' ..."
#echo ""
#echo "Compiling '"$(basename "$sketch")"' ..."
mkdir -p "$ARDUINO_BUILD_DIR"
mkdir -p "$ARDUINO_CACHE_DIR"
$ARDUINO_IDE_PATH/arduino-builder -compile -logger=human -core-api-version=10810 \
@ -131,14 +131,14 @@ function count_sketches() # count_sketches <examples-path> <target-mcu>
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
if [[ "$sketchdirname.ino" != "$sketchname" ]]; then
continue
fi;
if [[ -f "$sketchdir/.skip.$target" ]]; then
elif [[ -f "$sketchdir/.skip.$target" ]]; then
continue
else
echo $sketch >> sketches.txt
sketchnum=$(($sketchnum + 1))
fi
echo $sketch >> sketches.txt
sketchnum=$(($sketchnum + 1))
done
return $sketchnum
}
@ -168,13 +168,13 @@ function build_sketches() # build_sketches <fqbn> <target-mcu> <examples-path> <
echo "ERROR: Chunks count must be positive number"
return 1
fi
if [ "$chunk_idex" -ge "$chunks_num" ]; then
if [ "$chunk_idex" -ge "$chunks_num" ] && [ "$chunks_num" -ge 2 ]; then
echo "ERROR: Chunk index must be less than chunks count"
return 1
fi
set +e
count_sketches "$examples"
count_sketches "$examples" "$target"
local sketchcount=$?
set -e
local sketches=$(cat sketches.txt)
@ -186,19 +186,27 @@ function build_sketches() # build_sketches <fqbn> <target-mcu> <examples-path> <
chunk_size=$(( $chunk_size + 1 ))
fi
local start_index=$(( $chunk_idex * $chunk_size ))
if [ "$sketchcount" -le "$start_index" ]; then
echo "Skipping job"
return 0
fi
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
if [ "$end_index" -gt "$sketchcount" ]; then
local start_index=0
local end_index=0
if [ "$chunk_idex" -ge "$chunks_num" ]; then
start_index=$chunk_idex
end_index=$sketchcount
fi
else
start_index=$(( $chunk_idex * $chunk_size ))
if [ "$sketchcount" -le "$start_index" ]; then
echo "Skipping job"
return 0
fi
end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
if [ "$end_index" -gt "$sketchcount" ]; then
end_index=$sketchcount
fi
fi
local start_num=$(( $start_index + 1 ))
echo "Found $sketchcount Sketches";
echo "Found $sketchcount Sketches for target '$target'";
echo "Chunk Index : $chunk_idex"
echo "Chunk Count : $chunks_num"
echo "Chunk Size : $chunk_size"
echo "Start Sketch: $start_num"
@ -218,6 +226,8 @@ function build_sketches() # build_sketches <fqbn> <target-mcu> <examples-path> <
|| [ "$sketchnum" -gt "$end_index" ]; then
continue
fi
echo ""
echo "Building Sketch Index $(($sketchnum - 1)) - $sketchdirname"
build_sketch "$fqbn" "$sketch" "$xtra_opts"
local result=$?
if [ $result -ne 0 ]; then

View File

@ -87,9 +87,15 @@ function git_safe_upload_to_pages(){
EVENT_JSON=`cat $GITHUB_EVENT_PATH`
echo "GITHUB_EVENT_PATH: $GITHUB_EVENT_PATH"
echo "EVENT_JSON: $EVENT_JSON"
pages_added=`echo "$EVENT_JSON" | jq -r '.commits[].added[]'`
echo "added: $pages_added"
pages_modified=`echo "$EVENT_JSON" | jq -r '.commits[].modified[]'`
echo "modified: $pages_modified"
pages_removed=`echo "$EVENT_JSON" | jq -r '.commits[].removed[]'`
echo "removed: $pages_removed"
for page in $pages_added; do
if [[ $page != "README.md" && $page != "docs/"* ]]; then

View File

@ -24,7 +24,7 @@ BUILD_PIO=0
if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then
CHUNK_INDEX=0
CHUNKS_CNT=1
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ]; then
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ] && [ "$CHUNKS_CNT" -ge 2 ]; then
CHUNK_INDEX=$CHUNKS_CNT
elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
BUILD_PIO=1
@ -69,6 +69,19 @@ if [ "$BUILD_PIO" -eq 0 ]; then
else
build_sketches "$FQBN" "$TARGET" "$ARDUINO_ESP32_PATH/libraries" "$CHUNK_INDEX" "$CHUNKS_CNT"
fi
# ArduinoIDE ESP32C3 Test
TARGET="esp32c3"
FQBN="espressif:esp32:esp32c3:PartitionScheme=huge_app"
if [ "$OS_IS_WINDOWS" == "1" ]; then
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino"
elif [ "$OS_IS_MACOS" == "1" ]; then
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino"
else
build_sketches "$FQBN" "$TARGET" "$ARDUINO_ESP32_PATH/libraries" "$CHUNK_INDEX" "$CHUNKS_CNT"
fi
else
source ./.github/scripts/install-platformio-esp32.sh
# PlatformIO ESP32 Test

View File

@ -183,6 +183,7 @@ cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.py" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.exe" "$PKG_DIR/tools/"
cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/"
cp -Rf "$GITHUB_WORKSPACE/tools/sdk" "$PKG_DIR/tools/"
cp -f $GITHUB_WORKSPACE/tools/platformio-build*.py "$PKG_DIR/tools/"
# Remove unnecessary files in the package folder
echo "Cleaning up folders ..."
@ -194,6 +195,7 @@ echo "Generating platform.txt..."
cat "$GITHUB_WORKSPACE/platform.txt" | \
sed "s/version=.*/version=$ver$extent/g" | \
sed 's/runtime.tools.xtensa-esp32-elf-gcc.path={runtime.platform.path}\/tools\/xtensa-esp32-elf//g' | \
sed 's/runtime.tools.xtensa-esp32s2-elf-gcc.path={runtime.platform.path}\/tools\/xtensa-esp32s2-elf//g' | \
sed 's/tools.esptool_py.path={runtime.platform.path}\/tools\/esptool/tools.esptool_py.path=\{runtime.tools.esptool_py.path\}/g' \
> "$PKG_DIR/platform.txt"
@ -254,17 +256,30 @@ releasesJson=`curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.
if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi
set +e
prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name')
prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name')
prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
prev_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false)) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
prev_branch_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
prev_branch_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[0].tag_name")
shopt -s nocasematch
if [ "$prev_any_release" == "$RELEASE_TAG" ]; then
prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name')
prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name')
if [ "$prev_release" == "$RELEASE_TAG" ]; then
prev_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false)) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
fi
if [ "$prev_any_release" == "$RELEASE_TAG" ]; then
prev_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false)) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
fi
if [ "$prev_branch_release" == "$RELEASE_TAG" ]; then
prev_branch_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .prerelease == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
fi
if [ "$prev_branch_any_release" == "$RELEASE_TAG" ]; then
prev_branch_any_release=$(echo "$releasesJson" | jq -e -r ". | map(select(.draft == false and .target_commitish == \"$RELEASE_BRANCH\")) | sort_by(.published_at | - fromdateiso8601) | .[1].tag_name")
fi
COMMITS_SINCE_RELEASE="$prev_any_release"
shopt -u nocasematch
set -e
echo "Previous Release: $prev_release"
echo "Previous (any)release: $prev_any_release"
echo
# Merge package JSONs with previous releases
if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
echo "Merging with JSON from $prev_any_release ..."
@ -272,17 +287,12 @@ if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
fi
if [ "$RELEASE_PRE" == "false" ]; then
COMMITS_SINCE_RELEASE="$prev_release"
if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then
echo "Merging with JSON from $prev_release ..."
merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"
fi
fi
echo "Previous Release: $prev_release"
echo "Previous (any)release: $prev_any_release"
echo
# Upload package JSONs
echo "Uploading $PACKAGE_JSON_DEV ..."
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
@ -327,21 +337,35 @@ if [ $arrLen > 3 ] && [ "${msgArray[0]:0:3}" == "tag" ]; then
fi
# Append Commit Messages
echo
echo "Previous Branch Release: $prev_branch_release"
echo "Previous Branch (any)release: $prev_branch_any_release"
echo
commitFile="$OUTPUT_DIR/commits.txt"
COMMITS_SINCE_RELEASE="$prev_branch_any_release"
if [ "$RELEASE_PRE" == "false" ]; then
COMMITS_SINCE_RELEASE="$prev_branch_release"
fi
if [ ! -z "$COMMITS_SINCE_RELEASE" ] && [ "$COMMITS_SINCE_RELEASE" != "null" ]; then
echo "Getting commits since $COMMITS_SINCE_RELEASE ..."
commitFile=$OUTPUT_DIR/commits.txt
git -C "$GITHUB_WORKSPACE" log --oneline "$COMMITS_SINCE_RELEASE..HEAD" > "$OUTPUT_DIR/commits.txt"
releaseNotes+=$'\r\n##### Commits\r\n'
IFS=$'\n'
for next in `cat $commitFile`
do
IFS=' ' read -r commitId commitMsg <<< "$next"
commitLine="- [$commitId](https://github.com/$GITHUB_REPOSITORY/commit/$commitId) $commitMsg"
releaseNotes+="$commitLine"
releaseNotes+=$'\r\n'
done
rm -f $commitFile
git -C "$GITHUB_WORKSPACE" log --oneline -n 500 "$COMMITS_SINCE_RELEASE..HEAD" > "$commitFile"
elif [ "$RELEASE_BRANCH" != "master" ]; then
echo "Getting all commits on branch '$RELEASE_BRANCH' ..."
git -C "$GITHUB_WORKSPACE" log --oneline -n 500 --cherry-pick --left-only --no-merges HEAD...origin/master > "$commitFile"
else
echo "Getting all commits on master ..."
git -C "$GITHUB_WORKSPACE" log --oneline -n 500 --no-merges > "$commitFile"
fi
releaseNotes+=$'\r\n##### Commits\r\n'
IFS=$'\n'
for next in `cat $commitFile`
do
IFS=' ' read -r commitId commitMsg <<< "$next"
commitLine="- [$commitId](https://github.com/$GITHUB_REPOSITORY/commit/$commitId) $commitMsg"
releaseNotes+="$commitLine"
releaseNotes+=$'\r\n'
done
rm -f $commitFile
# Prepend the original release body
if [ "${RELEASE_BODY: -1}" == $'\r' ]; then

11
.github/stale.yml vendored
View File

@ -12,12 +12,9 @@ onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- pinned
- security
- "to be implemented"
- "for reference"
- "move to PR"
- "enhancement"
- "Type: For reference"
- "Type: To be implemented"
- "Type: Feature request"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
@ -29,7 +26,7 @@ exemptMilestones: false
exemptAssignees: false
# Label to use when marking as stale
staleLabel: stale
staleLabel: Status: Stale
# Comment to post when marking as stale. Set to `false` to disable
markComment: >

View File

@ -4,9 +4,12 @@ on:
push:
branches:
- master
- pages
paths:
- 'README.md'
- 'docs/**'
- '.github/scripts/on-pages.sh'
- '.github/workflows/gh-pages.yml'
jobs:

View File

@ -11,6 +11,8 @@ jobs:
steps:
- uses: actions/checkout@master
with:
fetch-depth: 0
- uses: actions/setup-python@v1
with:
python-version: '3.x'

5
.gitignore vendored
View File

@ -1,10 +1,11 @@
tools/xtensa-esp32-elf
tools/xtensa-esp32s2-elf
tools/riscv32-esp-elf
tools/dist
tools/esptool
tools/esptool.exe
tools/mkspiffs/mkspiffs
tools/mkspiffs/mkspiffs.exe
tools/mkspiffs
tools/mklittlefs
.DS_Store
#Ignore files built by Visual Studio/Visual Micro

View File

@ -7,6 +7,7 @@ set(CORE_SRCS
cores/esp32/esp32-hal-dac.c
cores/esp32/esp32-hal-gpio.c
cores/esp32/esp32-hal-i2c.c
cores/esp32/esp32-hal-log.c
cores/esp32/esp32-hal-ledc.c
cores/esp32/esp32-hal-matrix.c
cores/esp32/esp32-hal-misc.c
@ -44,6 +45,9 @@ set(LIBRARY_SRCS
libraries/ArduinoOTA/src/ArduinoOTA.cpp
libraries/AsyncUDP/src/AsyncUDP.cpp
libraries/BluetoothSerial/src/BluetoothSerial.cpp
libraries/BluetoothSerial/src/BTAddress.cpp
libraries/BluetoothSerial/src/BTAdvertisedDeviceSet.cpp
libraries/BluetoothSerial/src/BTScanResultsSet.cpp
libraries/DNSServer/src/DNSServer.cpp
libraries/EEPROM/src/EEPROM.cpp
libraries/ESPmDNS/src/ESPmDNS.cpp
@ -55,6 +59,11 @@ set(LIBRARY_SRCS
libraries/LITTLEFS/src/LITTLEFS.cpp
libraries/NetBIOS/src/NetBIOS.cpp
libraries/Preferences/src/Preferences.cpp
libraries/RainMaker/src/RMaker.cpp
libraries/RainMaker/src/RMakerNode.cpp
libraries/RainMaker/src/RMakerParam.cpp
libraries/RainMaker/src/RMakerDevice.cpp
libraries/RainMaker/src/RMakerType.cpp
libraries/SD_MMC/src/SD_MMC.cpp
libraries/SD/src/SD.cpp
libraries/SD/src/sd_diskio.cpp
@ -118,7 +127,7 @@ set(BLE_SRCS
set(includedirs
variants/esp32/
variants/${IDF_TARGET}/
cores/esp32/
libraries/ArduinoOTA/src
libraries/AsyncUDP/src
@ -135,6 +144,7 @@ set(includedirs
libraries/LITTLEFS/src
libraries/NetBIOS/src
libraries/Preferences/src
libraries/RainMaker/src
libraries/SD_MMC/src
libraries/SD/src
libraries/SimpleBLE/src
@ -152,7 +162,14 @@ set(includedirs
set(srcs ${CORE_SRCS} ${LIBRARY_SRCS} ${BLE_SRCS})
set(priv_includes cores/esp32/libb64)
set(requires spi_flash mbedtls mdns esp_adc_cal)
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support openssl bt tinyusb main)
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support openssl bt arduino_tinyusb main)
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ArduinoOTA)
list(APPEND priv_requires esp_https_ota)
endif()
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_LITTLEFS)
list(APPEND priv_requires esp_littlefs)
endif()
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})

View File

@ -40,6 +40,12 @@ config ARDUINO_RUNNING_CORE
default 1 if ARDUINO_RUN_CORE1
default -1 if ARDUINO_RUN_NO_AFFINITY
config ARDUINO_LOOP_STACK_SIZE
int "Loop thread stack size"
default 8192
help
Amount of stack available for the Arduino task.
choice ARDUINO_EVENT_RUNNING_CORE
bool "Core on which Arduino's event handler is running"
default ARDUINO_EVENT_RUN_CORE1
@ -265,6 +271,12 @@ config ARDUINO_SELECTIVE_HTTPClient
select ARDUINO_SELECTIVE_WiFiClientSecure
default y
config ARDUINO_SELECTIVE_LITTLEFS
bool "Enable LITTLEFS"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_NetBIOS
bool "Enable NetBIOS"
depends on ARDUINO_SELECTIVE_COMPILATION
@ -331,6 +343,12 @@ config ARDUINO_SELECTIVE_WiFiClientSecure
select ARDUINO_SELECTIVE_WiFi
default y
config ARDUINO_SELECTIVE_WiFiProv
bool "Enable WiFiProv"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
default y
config ARDUINO_SELECTIVE_Wire
bool "Enable Wire"
depends on ARDUINO_SELECTIVE_COMPILATION

View File

@ -44,6 +44,8 @@ Finally, if you are sure no one else had the issue, follow the [ISSUE_TEMPLATE](
![Pin Functions](docs/esp32_pinmap.png)
![ESP32S2_Pinmap](docs/esp32s2_pinmap.png)
### Tip
Sometimes to program ESP32 via serial you must keep GPIO0 LOW during the programming process

2023
boards.txt

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,8 @@ extern "C" {
#include "soc/efuse_reg.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/spi_flash.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/spi_flash.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
@ -265,6 +267,10 @@ const char * EspClass::getChipModel(void)
}
#elif CONFIG_IDF_TARGET_ESP32S2
return "ESP32-S2";
#elif CONFIG_IDF_TARGET_ESP32S3
return "ESP32-S3";
#elif CONFIG_IDF_TARGET_ESP32C3
return "ESP32-C3";
#endif
}

View File

@ -50,7 +50,7 @@ HardwareSerial Serial2(2);
HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {}
void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms)
void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms, uint8_t rxfifo_full_thrhd)
{
if(0 > _uart_nr || _uart_nr > 2) {
log_e("Serial number is invalid, please use 0, 1 or 2");
@ -66,6 +66,9 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
#elif CONFIG_IDF_TARGET_ESP32S2
rxPin = 44;
txPin = 43;
#elif CONFIG_IDF_TARGET_ESP32C3
rxPin = 20;
txPin = 21;
#endif
}
if(_uart_nr == 1 && rxPin < 0 && txPin < 0) {
@ -78,7 +81,7 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
txPin = TX2;
}
#endif
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert);
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert, rxfifo_full_thrhd);
_tx_pin = txPin;
_rx_pin = rxPin;
@ -94,7 +97,7 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
if(detectedBaudRate) {
delay(100); // Give some time...
_uart = uartBegin(_uart_nr, detectedBaudRate, config, rxPin, txPin, 256, invert);
_uart = uartBegin(_uart_nr, detectedBaudRate, config, rxPin, txPin, 256, invert, rxfifo_full_thrhd);
} else {
log_e("Could not detect baudrate. Serial data at the port must be present within the timeout for detection to be possible");
_uart = NULL;
@ -114,6 +117,7 @@ void HardwareSerial::end()
if(uartGetDebug() == _uart_nr) {
uartSetDebug(0);
}
delay(10);
log_v("pins %d %d",_tx_pin, _rx_pin);
uartEnd(_uart, _tx_pin, _rx_pin);
_uart = 0;

View File

@ -55,7 +55,7 @@ class HardwareSerial: public Stream
public:
HardwareSerial(int uart_nr);
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL);
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL, uint8_t rxfifo_full_thrhd = 112);
void end();
void updateBaudRate(unsigned long baud);
int available(void);

View File

@ -28,6 +28,8 @@
#include "esp32/rom/md5_hash.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/md5_hash.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/md5_hash.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif

View File

@ -73,6 +73,11 @@ public:
}
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
// add availableForWrite to make compatible with Arduino Print.h
// default to zero, meaning "a single write may block"
// should be overriden by subclasses with buffering
virtual int availableForWrite() { return 0; }
size_t print(const __FlashStringHelper *);
size_t print(const String &);
size_t print(const char[]);

View File

@ -14,7 +14,7 @@
#include "esp32-hal.h"
#include "esp32-hal-tinyusb.h"
#include "USB.h"
#if CONFIG_USB_ENABLED
#if CONFIG_TINYUSB_ENABLED
#ifndef USB_VID
#define USB_VID USB_ESPRESSIF_VID
@ -32,11 +32,7 @@
#define USB_SERIAL "0"
#endif
extern "C" {
#include "tinyusb.h"
}
#if CFG_TUD_DFU_RT
#if CFG_TUD_DFU_RUNTIME
static uint16_t load_dfu_descriptor(uint8_t * dst, uint8_t * itf)
{
#define DFU_ATTR_CAN_DOWNLOAD 1
@ -59,7 +55,7 @@ void tud_dfu_rt_reboot_to_dfu(void)
{
usb_persist_restart(RESTART_BOOTLOADER_DFU);
}
#endif /* CFG_TUD_DFU_RT */
#endif /* CFG_TUD_DFU_RUNTIME */
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_EVENTS);
@ -187,9 +183,9 @@ ESPUSB::operator bool() const
}
bool ESPUSB::enableDFU(){
#if CFG_TUD_DFU_RT
#if CFG_TUD_DFU_RUNTIME
return tinyusb_enable_interface(USB_INTERFACE_DFU, TUD_DFU_RT_DESC_LEN, load_dfu_descriptor) == ESP_OK;
#endif /* CFG_TUD_DFU_RT */
#endif /* CFG_TUD_DFU_RUNTIME */
return false;
}
@ -335,4 +331,4 @@ const char * ESPUSB::webUSBURL(void){
ESPUSB USB;
#endif /* CONFIG_USB_ENABLED */
#endif /* CONFIG_TINYUSB_ENABLED */

View File

@ -14,7 +14,7 @@
#pragma once
#include "sdkconfig.h"
#if CONFIG_USB_ENABLED
#if CONFIG_TINYUSB_ENABLED
#include "Arduino.h"
#include "USBCDC.h"
@ -115,4 +115,4 @@ class ESPUSB {
extern ESPUSB USB;
#endif /* CONFIG_USB_ENABLED */
#endif /* CONFIG_TINYUSB_ENABLED */

View File

@ -15,16 +15,12 @@
#include "esp32-hal-tinyusb.h"
#include "USB.h"
#include "USBCDC.h"
#if CONFIG_USB_ENABLED
#if CONFIG_TINYUSB_ENABLED
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_CDC_EVENTS);
esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait);
esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg);
extern "C" {
#include "tinyusb.h"
}
#if CFG_TUD_CDC
#define MAX_USB_CDC_DEVICES 2
USBCDC * devices[MAX_USB_CDC_DEVICES] = {NULL, NULL};
@ -202,22 +198,26 @@ void USBCDC::_onLineState(bool _dtr, bool _rts){
void USBCDC::_onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _parity, uint8_t _data_bits){
if(bit_rate != _bit_rate || data_bits != _data_bits || stop_bits != _stop_bits || parity != _parity){
bit_rate = _bit_rate;
data_bits = _data_bits;
stop_bits = _stop_bits;
parity = _parity;
arduino_usb_cdc_event_data_t p = {0};
p.line_coding.bit_rate = bit_rate;
p.line_coding.data_bits = data_bits;
p.line_coding.stop_bits = stop_bits;
p.line_coding.parity = parity;
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_CODING_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
if(bit_rate == 9600 && _bit_rate == 1200){
usb_persist_restart(RESTART_BOOTLOADER);
} else {
bit_rate = _bit_rate;
data_bits = _data_bits;
stop_bits = _stop_bits;
parity = _parity;
arduino_usb_cdc_event_data_t p = {0};
p.line_coding.bit_rate = bit_rate;
p.line_coding.data_bits = data_bits;
p.line_coding.stop_bits = stop_bits;
p.line_coding.parity = parity;
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_CODING_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
}
}
}
void USBCDC::_onRX(){
uint8_t buf[CONFIG_USB_CDC_RX_BUFSIZE+1];
uint32_t count = tud_cdc_n_read(itf, buf, CONFIG_USB_CDC_RX_BUFSIZE);
uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE+1];
uint32_t count = tud_cdc_n_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE);
for(uint32_t i=0; i<count; i++){
if(rx_queue == NULL || !xQueueSend(rx_queue, buf+i, 0)){
return;
@ -333,6 +333,6 @@ USBCDC::operator bool() const
USBCDC Serial(0);
#endif
#endif /* CONFIG_USB_CDC_ENABLED */
#endif /* CONFIG_TINYUSB_CDC_ENABLED */
#endif /* CONFIG_USB_ENABLED */
#endif /* CONFIG_TINYUSB_ENABLED */

View File

@ -17,7 +17,7 @@
#include "Stream.h"
#include "esp32-hal.h"
#if CONFIG_USB_CDC_ENABLED
#if CONFIG_TINYUSB_CDC_ENABLED
#include "esp_event.h"
@ -130,4 +130,4 @@ protected:
extern USBCDC Serial;
#endif
#endif /* CONFIG_USB_CDC_ENABLED */
#endif /* CONFIG_TINYUSB_CDC_ENABLED */

View File

@ -27,6 +27,7 @@ extern "C" {
#include <stdlib.h>
#include "esp_system.h"
}
#include "esp32-hal-log.h"
void randomSeed(unsigned long seed)
{
@ -69,7 +70,10 @@ long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long dividend = out_max - out_min;
const long divisor = in_max - in_min;
const long delta = x - in_min;
if(divisor == 0){
log_e("Invalid map input range, min == max");
return -1; //AVR returns -1, SAM returns 0
}
return (delta * dividend + (divisor / 2)) / divisor + out_min;
}

View File

@ -130,9 +130,9 @@ String::~String() {
inline void String::init(void) {
setSSO(false);
setBuffer(nullptr);
setCapacity(0);
setLen(0);
setBuffer(nullptr);
}
void String::invalidate(void) {
@ -159,7 +159,7 @@ unsigned char String::changeBuffer(unsigned int maxStrLen) {
// Already using SSO, nothing to do
uint16_t oldLen = len();
setSSO(true);
setLen(oldLen);
setLen(oldLen);
return 1;
} else { // if bufptr && !isSSO()
// Using bufptr, need to shrink into sso.buff
@ -168,8 +168,8 @@ unsigned char String::changeBuffer(unsigned int maxStrLen) {
free(wbuffer());
uint16_t oldLen = len();
setSSO(true);
setLen(oldLen);
memcpy(wbuffer(), temp, maxStrLen);
setLen(oldLen);
return 1;
}
}
@ -193,8 +193,8 @@ unsigned char String::changeBuffer(unsigned int maxStrLen) {
}
setSSO(false);
setCapacity(newSize - 1);
setLen(oldLen); // Needed in case of SSO where len() never existed
setBuffer(newbuffer);
setLen(oldLen); // Needed in case of SSO where len() never existed
return 1;
}
return 0;
@ -209,8 +209,8 @@ String & String::copy(const char *cstr, unsigned int length) {
invalidate();
return *this;
}
setLen(length);
memmove(wbuffer(), cstr, length + 1);
setLen(length);
return *this;
}
@ -219,8 +219,8 @@ String & String::copy(const __FlashStringHelper *pstr, unsigned int length) {
invalidate();
return *this;
}
setLen(length);
memcpy_P(wbuffer(), (PGM_P)pstr, length + 1); // We know wbuffer() cannot ever be in PROGMEM, so memcpy safe here
setLen(length);
return *this;
}
@ -250,8 +250,8 @@ void String::move(String &rhs) {
setLen(rhs.len());
rhs.setSSO(false);
rhs.setCapacity(0);
rhs.setLen(0);
rhs.setBuffer(nullptr);
rhs.setLen(0);
}
#endif
@ -744,6 +744,7 @@ void String::replace(const String& find, const String& replace) {
}
} else if(diff < 0) {
char *writeTo = wbuffer();
unsigned int l = len();
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
unsigned int n = foundAt - readFrom;
memmove(writeTo, readFrom, n);
@ -751,9 +752,10 @@ void String::replace(const String& find, const String& replace) {
memmove(writeTo, replace.buffer(), replace.len());
writeTo += replace.len();
readFrom = foundAt + find.len();
setLen(len() + diff);
l += diff;
}
memmove(writeTo, readFrom, strlen(readFrom)+1);
setLen(l);
} else {
unsigned int size = len(); // compute size needed for result
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
@ -768,7 +770,7 @@ void String::replace(const String& find, const String& replace) {
while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
readFrom = wbuffer() + index + find.len();
memmove(readFrom + diff, readFrom, len() - (readFrom - buffer()));
int newLen = len() + diff;
int newLen = len() + diff;
memmove(wbuffer() + index, replace.buffer(), replace.len());
setLen(newLen);
wbuffer()[newLen] = 0;
@ -796,8 +798,8 @@ void String::remove(unsigned int index, unsigned int count) {
}
char *writeTo = wbuffer() + index;
unsigned int newlen = len() - count;
setLen(newlen);
memmove(writeTo, wbuffer() + index + count, newlen - index);
setLen(newlen);
wbuffer()[newlen] = 0;
}
@ -827,9 +829,9 @@ void String::trim(void) {
while(isspace(*end) && end >= begin)
end--;
unsigned int newlen = end + 1 - begin;
setLen(newlen);
if(begin > buffer())
memmove(wbuffer(), begin, newlen);
setLen(newlen);
wbuffer()[newlen] = 0;
}

View File

@ -281,8 +281,8 @@ class String {
// Contains the string info when we're not in SSO mode
struct _ptr {
char * buff;
uint16_t cap;
uint16_t len;
uint32_t cap;
uint32_t len;
};
// This allows strings up up to 11 (10 + \0 termination) without any extra space.
enum { SSOSIZE = sizeof(struct _ptr) + 4 - 1 }; // Characters to allocate space for SSO, must be 12 or more
@ -291,7 +291,11 @@ class String {
unsigned char len : 7; // Ensure only one byte is allocated by GCC for the bitfields
unsigned char isSSO : 1;
} __attribute__((packed)); // Ensure that GCC doesn't expand the flag byte to a 32-bit word for alignment issues
enum { CAPACITY_MAX = 65535 }; // If typeof(cap) changed from uint16_t, be sure to update this enum to the max value storable in the type
#ifdef BOARD_HAS_PSRAM
enum { CAPACITY_MAX = 3145728 };
#else
enum { CAPACITY_MAX = 65535 };
#endif
union {
struct _ptr ptr;
struct _sso sso;
@ -301,9 +305,19 @@ class String {
inline unsigned int len() const { return isSSO() ? sso.len : ptr.len; }
inline unsigned int capacity() const { return isSSO() ? (unsigned int)SSOSIZE - 1 : ptr.cap; } // Size of max string not including terminal NUL
inline void setSSO(bool set) { sso.isSSO = set; }
inline void setLen(int len) { if (isSSO()) sso.len = len; else ptr.len = len; }
inline void setLen(int len) {
if (isSSO()) {
sso.len = len;
sso.buff[len] = 0;
} else {
ptr.len = len;
if (ptr.buff) {
ptr.buff[len] = 0;
}
}
}
inline void setCapacity(int cap) { if (!isSSO()) ptr.cap = cap; }
inline void setBuffer(char *buff) { if (!isSSO()) ptr.buff = buff; }
inline void setBuffer(char *buff) { if (!isSSO()) ptr.buff = buff; }
// Buffer accessor functions
inline const char *buffer() const { return (const char *)(isSSO() ? sso.buff : ptr.buff); }
inline char *wbuffer() const { return isSSO() ? const_cast<char *>(sso.buff) : ptr.buff; } // Writable version of buffer

View File

@ -16,16 +16,15 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_attr.h"
#include "soc/rtc_io_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "driver/adc.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp_adc_cal.h"
#include "soc/sens_reg.h"
#include "soc/rtc_io_reg.h"
#include "esp32/rom/ets_sys.h"
#include "esp_intr_alloc.h"
#define DEFAULT_VREF 1100
@ -34,6 +33,10 @@ static uint16_t __analogVRef = 0;
static uint8_t __analogVRefPin = 0;
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#include "soc/sens_reg.h"
#include "soc/rtc_io_reg.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/ets_sys.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
@ -51,7 +54,9 @@ void __analogSetClockDiv(uint8_t clockDiv){
clockDiv = 1;
}
__analogClockDiv = clockDiv;
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
adc_set_clk_div(__analogClockDiv);
#endif
}
void __analogSetAttenuation(adc_attenuation_t attenuation)
@ -114,11 +119,14 @@ bool __adcAttachPin(uint8_t pin){
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, touch);
}
#endif
} else if(pin == 25){
}
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
else if(pin == 25){
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);//stop dac1
} else if(pin == 26){
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);//stop dac2
}
#endif
pinMode(pin, ANALOG);
__analogSetPinAttenuation(pin, __analogAttenuation);

View File

@ -18,11 +18,12 @@
bool btInUse(){ return true; }
#ifdef CONFIG_BLUEDROID_ENABLED
#include "esp_bt.h"
#ifdef CONFIG_CLASSIC_BT_ENABLED
#ifdef CONFIG_BTDM_CONTROLLER_MODE_BTDM
#define BT_MODE ESP_BT_MODE_BTDM
#elif defined(CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY)
#define BT_MODE ESP_BT_MODE_CLASSIC_BT
#else
#define BT_MODE ESP_BT_MODE_BLE
#endif
@ -79,7 +80,7 @@ bool btStop(){
return false;
}
#else
#else // CONFIG_BT_ENABLED
bool btStarted()
{
return false;
@ -94,6 +95,6 @@ bool btStop()
{
return false;
}
#endif
#endif
#endif // CONFIG_BT_ENABLED

View File

@ -16,7 +16,6 @@
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "freertos/xtensa_timer.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "soc/rtc.h"
@ -29,9 +28,13 @@
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "freertos/xtensa_timer.h"
#include "esp32/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "freertos/xtensa_timer.h"
#include "esp32s2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/rtc.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
@ -141,10 +144,14 @@ bool removeApbChangeCallback(void * arg, apb_change_cb_t cb){
}
static uint32_t calculateApb(rtc_cpu_freq_config_t * conf){
#if CONFIG_IDF_TARGET_ESP32C3
return APB_CLK_FREQ;
#else
if(conf->freq_mhz >= 80){
return 80 * MHZ;
}
return (conf->source_freq_mhz * MHZ) / conf->div;
#endif
}
void esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us); //private in IDF
@ -219,8 +226,12 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
esp_timer_impl_update_apb_freq(apb / MHZ);
}
//Update FreeRTOS Tick Divisor
#if CONFIG_IDF_TARGET_ESP32C3
#else
uint32_t fcpu = (conf.freq_mhz >= 80)?(conf.freq_mhz * MHZ):(apb);
_xt_tick_divisor = fcpu / XT_TICK_PER_SEC;
#endif
//Call peripheral functions after the APB change
if(apb_change_callbacks){
triggerApbChangeCallback(APB_AFTER_CHANGE, capb, apb);

View File

@ -13,24 +13,29 @@
// limitations under the License.
#include "esp32-hal.h"
#include "esp_attr.h"
#if CONFIG_IDF_TARGET_ESP32
#include "soc/rtc_io_reg.h"
#define DAC1 25
#define DAC2 26
#elif CONFIG_IDF_TARGET_ESP32S2
#include "soc/rtc_io_reg.h"
#define DAC1 17
#define DAC2 18
#elif CONFIG_IDF_TARGET_ESP32C3
#define NODAC
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#ifndef NODAC
#include "esp_attr.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_periph.h"
#include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#include "driver/dac.h"
#if CONFIG_IDF_TARGET_ESP32
#define DAC1 25
#define DAC2 26
#elif CONFIG_IDF_TARGET_ESP32S2
#define DAC1 17
#define DAC2 18
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
void ARDUINO_ISR_ATTR __dacWrite(uint8_t pin, uint8_t value)
{
if(pin < DAC1 || pin > DAC2){
@ -54,3 +59,5 @@ void ARDUINO_ISR_ATTR __dacWrite(uint8_t pin, uint8_t value)
}
extern void dacWrite(uint8_t pin, uint8_t value) __attribute__ ((weak, alias("__dacWrite")));
#endif

View File

@ -20,23 +20,25 @@
#include "soc/gpio_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_struct.h"
#include "soc/rtc_io_reg.h"
#include "driver/gpio.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#include "esp32/rom/gpio.h"
#include "esp_intr_alloc.h"
#include "soc/rtc_io_reg.h"
#define GPIO_FUNC 2
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#include "esp32s2/rom/gpio.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
#include "soc/rtc_io_reg.h"
#define GPIO_FUNC 1
#else
#error Target CONFIG_IDF_TARGET is not supported
#define USE_ESP_IDF_GPIO 1
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
@ -157,7 +159,45 @@ static InterruptHandle_t __pinInterruptHandlers[SOC_GPIO_PIN_COUNT] = {0,};
extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
{
#if USE_ESP_IDF_GPIO
if (!GPIO_IS_VALID_GPIO(pin)) {
return;
}
gpio_config_t conf = {
.pin_bit_mask = (1ULL<<pin), /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
.mode = GPIO_MODE_DISABLE, /*!< GPIO mode: set input/output mode */
.pull_up_en = GPIO_PULLUP_DISABLE, /*!< GPIO pull-up */
.pull_down_en = GPIO_PULLDOWN_DISABLE, /*!< GPIO pull-down */
.intr_type = GPIO_INTR_DISABLE /*!< GPIO interrupt type */
};
if (mode < 0x20) {//io
conf.mode = mode & (INPUT | OUTPUT);
if (mode & OPEN_DRAIN) {
conf.mode |= GPIO_MODE_DEF_OD;
}
if (mode & PULLUP) {
conf.pull_up_en = GPIO_PULLUP_ENABLE;
}
if (mode & PULLDOWN) {
conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
}
}
gpio_config(&conf);
if(mode == SPECIAL){
#if CONFIG_IDF_TARGET_ESP32
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin], (uint32_t)(((pin)==RX||(pin)==TX)?0:1));
#elif CONFIG_IDF_TARGET_ESP32S2
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin], (uint32_t)(((pin)==RX||(pin)==TX)?0:2));
#endif
} else if(mode == ANALOG){
#if !CONFIG_IDF_TARGET_ESP32C3
//adc_gpio_init(ADC_UNIT_1, ADC_CHANNEL_0);
#endif
} else if(mode >= 0x20 && mode < ANALOG) {//function
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin], mode >> 5);
}
#else
if(!digitalPinIsValid(pin)) {
return;
}
@ -228,11 +268,7 @@ extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
pinFunction |= FUN_IE;//input enable but required for output as well?
if(mode & (INPUT | OUTPUT)) {
#if CONFIG_IDF_TARGET_ESP32
pinFunction |= ((uint32_t)2 << MCU_SEL_S);
#elif CONFIG_IDF_TARGET_ESP32S2
pinFunction |= ((uint32_t)1 << MCU_SEL_S);
#endif
pinFunction |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S);
} else if(mode == SPECIAL) {
#if CONFIG_IDF_TARGET_ESP32
pinFunction |= ((uint32_t)(((pin)==RX||(pin)==TX)?0:1) << MCU_SEL_S);
@ -250,10 +286,20 @@ extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
}
GPIO.pin[pin].val = pinControl;
#endif
}
extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val)
{
#if USE_ESP_IDF_GPIO
gpio_set_level((gpio_num_t)pin, val);
#elif CONFIG_IDF_TARGET_ESP32C3
if (val) {
GPIO.out_w1ts.out_w1ts = (1 << pin);
} else {
GPIO.out_w1tc.out_w1tc = (1 << pin);
}
#else
if(val) {
if(pin < 32) {
GPIO.out_w1ts = ((uint32_t)1 << pin);
@ -267,18 +313,37 @@ extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val)
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
}
}
#endif
}
extern int ARDUINO_ISR_ATTR __digitalRead(uint8_t pin)
{
#if USE_ESP_IDF_GPIO
return gpio_get_level((gpio_num_t)pin);
#elif CONFIG_IDF_TARGET_ESP32C3
return (GPIO.in.data >> pin) & 0x1;
#else
if(pin < 32) {
return (GPIO.in >> pin) & 0x1;
} else if(pin < GPIO_PIN_COUNT) {
return (GPIO.in1.val >> (pin - 32)) & 0x1;
}
return 0;
#endif
}
#if USE_ESP_IDF_GPIO
static void ARDUINO_ISR_ATTR __onPinInterrupt(void * arg) {
InterruptHandle_t * isr = (InterruptHandle_t*)arg;
if(isr->fn) {
if(isr->arg){
((voidFuncPtrArg)isr->fn)(isr->arg);
} else {
isr->fn();
}
}
}
#else
static intr_handle_t gpio_intr_handle = NULL;
static void ARDUINO_ISR_ATTR __onPinInterrupt()
@ -320,6 +385,7 @@ static void ARDUINO_ISR_ATTR __onPinInterrupt()
} while(++pin<GPIO_PIN_COUNT);
}
}
#endif
extern void cleanupFunctional(void* arg);
@ -328,8 +394,17 @@ extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc,
static bool interrupt_initialized = false;
if(!interrupt_initialized) {
#if USE_ESP_IDF_GPIO
esp_err_t err = gpio_install_isr_service((int)ARDUINO_ISR_FLAG);
interrupt_initialized = (err == ESP_OK) || (err == ESP_ERR_INVALID_STATE);
#else
interrupt_initialized = true;
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, __onPinInterrupt, NULL, &gpio_intr_handle);
#endif
}
if(!interrupt_initialized) {
log_e("GPIO ISR Service Failed To Start");
return;
}
// if new attach without detach remove old info
@ -341,6 +416,14 @@ extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc,
__pinInterruptHandlers[pin].arg = arg;
__pinInterruptHandlers[pin].functional = functional;
#if USE_ESP_IDF_GPIO
gpio_set_intr_type((gpio_num_t)pin, (gpio_int_type_t)(intr_type & 0x7));
if(intr_type & 0x8){
gpio_wakeup_enable((gpio_num_t)pin, (gpio_int_type_t)(intr_type & 0x7));
}
gpio_isr_handler_add((gpio_num_t)pin, __onPinInterrupt, &__pinInterruptHandlers[pin]);
gpio_intr_enable((gpio_num_t)pin);
#else
esp_intr_disable(gpio_intr_handle);
#if CONFIG_IDF_TARGET_ESP32
if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU
@ -353,6 +436,7 @@ extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc,
#endif
GPIO.pin[pin].int_type = intr_type;
esp_intr_enable(gpio_intr_handle);
#endif
}
extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type)
@ -366,7 +450,13 @@ extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int intr_type)
extern void __detachInterrupt(uint8_t pin)
{
#if USE_ESP_IDF_GPIO
gpio_intr_disable((gpio_num_t)pin);
gpio_isr_handler_remove((gpio_num_t)pin);
gpio_wakeup_disable((gpio_num_t)pin);
#else
esp_intr_disable(gpio_intr_handle);
#endif
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg)
{
cleanupFunctional(__pinInterruptHandlers[pin].arg);
@ -375,9 +465,13 @@ extern void __detachInterrupt(uint8_t pin)
__pinInterruptHandlers[pin].arg = NULL;
__pinInterruptHandlers[pin].functional = false;
#if USE_ESP_IDF_GPIO
gpio_set_intr_type((gpio_num_t)pin, GPIO_INTR_DISABLE);
#else
GPIO.pin[pin].int_ena = 0;
GPIO.pin[pin].int_type = 0;
esp_intr_enable(gpio_intr_handle);
#endif
}

View File

@ -28,7 +28,7 @@ extern "C" {
#include "soc/soc_caps.h"
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
#define NUM_OUPUT_PINS 45
#define NUM_OUPUT_PINS 46
#define PIN_DAC1 17
#define PIN_DAC2 18
#else

View File

@ -21,16 +21,19 @@
#include "driver/periph_ctrl.h"
#include "soc/i2c_reg.h"
#include "soc/i2c_struct.h"
#include "soc/dport_reg.h"
#include "esp_attr.h"
#include "esp32-hal-cpu.h" // cpu clock change support 31DEC2018
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "soc/dport_reg.h"
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "soc/dport_reg.h"
#include "esp32s2/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/ets_sys.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
@ -1795,7 +1798,7 @@ struct i2c_struct_t {
static i2c_t * i2c_ports[2] = {NULL, NULL};
i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t clk_speed){
if(i2c_num >= 2){
if(i2c_num >= SOC_I2C_NUM){
return NULL;
}
if(!clk_speed){
@ -1816,7 +1819,7 @@ i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t clk_speed){
i2c_driver_delete((i2c_port_t)i2c_num);
}
i2c_config_t conf;
i2c_config_t conf = { };
conf.mode = I2C_MODE_MASTER;
conf.scl_io_num = (gpio_num_t)scl;
conf.sda_io_num = (gpio_num_t)sda;

View File

@ -17,19 +17,25 @@
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp32-hal-matrix.h"
#include "soc/dport_reg.h"
#include "soc/ledc_reg.h"
#include "soc/ledc_struct.h"
#include "driver/periph_ctrl.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "soc/dport_reg.h"
#include "esp32/rom/ets_sys.h"
#define LAST_CHAN (15)
#elif CONFIG_IDF_TARGET_ESP32S2
#include "soc/dport_reg.h"
#include "esp32s2/rom/ets_sys.h"
#define LAST_CHAN (7)
#define LEDC_DIV_NUM_HSTIMER0_V LEDC_CLK_DIV_LSTIMER0_V
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/ets_sys.h"
#define LAST_CHAN (7)
#define LEDC_DIV_NUM_HSTIMER0_V LEDC_CLK_DIV_LSTIMER0_V
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
@ -111,8 +117,7 @@ static void _ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, boo
static uint16_t _activeChannels = 0;
if(!tHasStarted) {
tHasStarted = true;
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST);
periph_module_enable(PERIPH_LEDC_MODULE);
LEDC.conf.apb_clk_sel = 1;//LS use apb clock
addApbChangeCallback((void*)&_activeChannels, _on_apb_change);
@ -302,7 +307,7 @@ void ledcAttachPin(uint8_t pin, uint8_t chan)
return;
}
pinMode(pin, OUTPUT);
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
pinMatrixOutAttach(pin, LEDC_LS_SIG_OUT0_IDX + chan, false, false);
#else
pinMatrixOutAttach(pin, ((chan/8)?LEDC_LS_SIG_OUT0_IDX:LEDC_HS_SIG_OUT0_IDX) + (chan%8), false, false);
@ -313,3 +318,12 @@ void ledcDetachPin(uint8_t pin)
{
pinMatrixOutDetach(pin, false, false);
}
double ledcChangeFrequency(uint8_t chan, double freq, uint8_t bit_num)
{
if (chan > 15) {
return 0;
}
double res_freq = _ledcSetupTimerFreq(chan, freq, bit_num);
return res_freq;
}

View File

@ -35,6 +35,7 @@ uint32_t ledcRead(uint8_t channel);
double ledcReadFreq(uint8_t channel);
void ledcAttachPin(uint8_t pin, uint8_t channel);
void ledcDetachPin(uint8_t pin);
double ledcChangeFrequency(uint8_t channel, double freq, uint8_t resolution_bits);
#ifdef __cplusplus

View File

@ -0,0 +1,19 @@
#ifndef __MY_LOG__
#define __MY_LOG__
#include "stdio.h"
#include "esp32-hal-log.h"
void log_to_esp(char* tag, esp_log_level_t level, const char *format, ...)
{
va_list va_args;
va_start(va_args, format);
char log_buffer[512];
int len = vsnprintf(log_buffer, sizeof(log_buffer), format, va_args);
if (len > 0)
{
ESP_LOG_LEVEL_LOCAL(level, tag, "%s", log_buffer);
}
va_end(va_args);
}
#endif

View File

@ -37,6 +37,9 @@ extern "C"
#define ARDUHAL_LOG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL
#else
#define ARDUHAL_LOG_LEVEL CORE_DEBUG_LEVEL
#ifdef USE_ESP_IDF_LOG
#define LOG_LOCAL_LEVEL CORE_DEBUG_LEVEL
#endif
#endif
#ifndef CONFIG_ARDUHAL_LOG_COLORS
@ -72,6 +75,8 @@ extern "C"
#define ARDUHAL_LOG_RESET_COLOR
#endif
const char * pathToFileName(const char * path);
int log_printf(const char *fmt, ...);
@ -79,55 +84,92 @@ int log_printf(const char *fmt, ...);
#define ARDUHAL_LOG_FORMAT(letter, format) ARDUHAL_LOG_COLOR_ ## letter "[%6u][" #letter "][%s:%u] %s(): " format ARDUHAL_LOG_RESET_COLOR "\r\n", (unsigned long) (esp_timer_get_time() / 1000ULL), pathToFileName(__FILE__), __LINE__, __FUNCTION__
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
#ifndef USE_ESP_IDF_LOG
#define log_v(format, ...) log_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
#define isr_log_v(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
#else
#define log_v(format, ...) do {log_to_esp(TAG, ESP_LOG_VERBOSE, format, ##__VA_ARGS__);}while(0)
#define isr_log_v(format, ...) do {ets_printf(LOG_FORMAT(V, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_v(format, ...)
#define isr_log_v(format, ...)
#endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
#ifndef USE_ESP_IDF_LOG
#define log_d(format, ...) log_printf(ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__)
#define isr_log_d(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__)
#else
#define log_d(format, ...) do {log_to_esp(TAG, ESP_LOG_DEBUG, format, ##__VA_ARGS__);}while(0)
#define isr_log_d(format, ...) do {ets_printf(LOG_FORMAT(D, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_d(format, ...)
#define isr_log_d(format, ...)
#endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
#ifndef USE_ESP_IDF_LOG
#define log_i(format, ...) log_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
#define isr_log_i(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
#else
#define log_i(format, ...) do {log_to_esp(TAG, ESP_LOG_INFO, format, ##__VA_ARGS__);}while(0)
#define isr_log_i(format, ...) do {ets_printf(LOG_FORMAT(I, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_i(format, ...)
#define isr_log_i(format, ...)
#endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_WARN
#ifndef USE_ESP_IDF_LOG
#define log_w(format, ...) log_printf(ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__)
#define isr_log_w(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__)
#else
#define log_w(format, ...) do {log_to_esp(TAG, ESP_LOG_WARN, format, ##__VA_ARGS__);}while(0)
#define isr_log_w(format, ...) do {ets_printf(LOG_FORMAT(W, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_w(format, ...)
#define isr_log_w(format, ...)
#endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
#ifndef USE_ESP_IDF_LOG
#define log_e(format, ...) log_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
#define isr_log_e(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
#else
#define log_e(format, ...) do {log_to_esp(TAG, ESP_LOG_ERROR, format, ##__VA_ARGS__);}while(0)
#define isr_log_e(format, ...) do {ets_printf(LOG_FORMAT(E, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_e(format, ...)
#define isr_log_e(format, ...)
#endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_NONE
#ifndef USE_ESP_IDF_LOG
#define log_n(format, ...) log_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
#define isr_log_n(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
#else
#define log_n(format, ...) do {log_to_esp(TAG, ESP_LOG_ERROR, format, ##__VA_ARGS__);}while(0)
#define isr_log_n(format, ...) do {ets_printf(LOG_FORMAT(E, format), esp_log_timestamp(), TAG, ##__VA_ARGS__);}while(0)
#endif
#else
#define log_n(format, ...)
#define isr_log_n(format, ...)
#endif
#include "esp_log.h"
#ifdef USE_ESP_IDF_LOG
#ifndef TAG
#define TAG "ARDUINO"
#endif
void log_to_esp(char* tag, esp_log_level_t level, const char* format, ...);
//#define log_n(format, ...) myLog(ESP_LOG_NONE, format, ##__VA_ARGS__)
#else
#ifdef CONFIG_ARDUHAL_ESP_LOG
#undef ESP_LOGE
#undef ESP_LOGW
@ -151,6 +193,7 @@ int log_printf(const char *fmt, ...);
#define ESP_EARLY_LOGD(tag, ...) isr_log_d(__VA_ARGS__)
#define ESP_EARLY_LOGV(tag, ...) isr_log_v(__VA_ARGS__)
#endif
#endif
#ifdef __cplusplus
}

View File

@ -21,6 +21,8 @@
#include "esp32/rom/gpio.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/gpio.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/gpio.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif

View File

@ -40,6 +40,10 @@
#include "esp32/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/rtc.h"
#include "driver/temp_sensor.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/rtc.h"
#include "driver/temp_sensor.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
@ -49,12 +53,25 @@
//Undocumented!!! Get chip temperature in Farenheit
//Source: https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/ESP32_int_temp_sensor/ESP32_int_temp_sensor.ino
#ifdef CONFIG_IDF_TARGET_ESP32
uint8_t temprature_sens_read();
float temperatureRead()
{
return (temprature_sens_read() - 32) / 1.8;
}
#else
float temperatureRead()
{
float result = NAN;
temp_sensor_config_t tsens = TSENS_CONFIG_DEFAULT();
temp_sensor_set_config(tsens);
temp_sensor_start();
temp_sensor_read_celsius(&result);
temp_sensor_stop();
return result;
}
#endif
void __yield()
{
@ -160,15 +177,15 @@ void delay(uint32_t ms)
void ARDUINO_ISR_ATTR delayMicroseconds(uint32_t us)
{
uint32_t m = micros();
uint64_t m = (uint64_t)esp_timer_get_time();
if(us){
uint32_t e = (m + us);
uint64_t e = (m + us);
if(m > e){ //overflow
while(micros() > e){
while((uint64_t)esp_timer_get_time() > e){
NOP();
}
}
while(micros() < e){
while((uint64_t)esp_timer_get_time() < e){
NOP();
}
}

View File

@ -28,15 +28,27 @@
*/
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#define MAX_CHANNELS 8
#define MAX_DATA_PER_CHANNEL 64
#define MAX_DATA_PER_ITTERATION 62
#elif CONFIG_IDF_TARGET_ESP32S2
#define MAX_CHANNELS 4
#define MAX_DATA_PER_CHANNEL 64
#define MAX_DATA_PER_ITTERATION 62
#elif CONFIG_IDF_TARGET_ESP32C3
#define MAX_CHANNELS 4
#define MAX_DATA_PER_CHANNEL 48
#define MAX_DATA_PER_ITTERATION 46
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#define MAX_DATA_PER_CHANNEL 64
#define MAX_DATA_PER_ITTERATION 62
#define _ABS(a) (a>0?a:-a)
#define _LIMIT(a,b) (a>b?b:a)
#if CONFIG_IDF_TARGET_ESP32C3
#define _INT_TX_END(channel) (1<<(channel))
#define _INT_RX_END(channel) (4<<(channel))
#define _INT_ERROR(channel) (16<<(channel))
#define _INT_THR_EVNT(channel) (256<<(channel))
#else
#define __INT_TX_END (1)
#define __INT_RX_END (2)
#define __INT_ERROR (4)
@ -46,6 +58,7 @@
#define _INT_RX_END(channel) (__INT_RX_END<<(channel*3))
#define _INT_ERROR(channel) (__INT_ERROR<<(channel*3))
#define _INT_THR_EVNT(channel) ((__INT_THR_EVNT)<<(channel))
#endif
#if CONFIG_DISABLE_HAL_LOCKS
# define RMT_MUTEX_LOCK(channel)
@ -55,7 +68,7 @@
# define RMT_MUTEX_UNLOCK(channel) xSemaphoreGive(g_rmt_objlocks[channel])
#endif /* CONFIG_DISABLE_HAL_LOCKS */
#define _RMT_INTERNAL_DEBUG
//#define _RMT_INTERNAL_DEBUG
#ifdef _RMT_INTERNAL_DEBUG
# define DEBUG_INTERRUPT_START(pin) digitalWrite(pin, 1);
# define DEBUG_INTERRUPT_END(pin) digitalWrite(pin, 0);
@ -162,12 +175,17 @@ bool rmtSetCarrier(rmt_obj_t* rmt, bool carrier_en, bool carrier_level, uint32_t
size_t channel = rmt->channel;
RMT_MUTEX_LOCK(channel);
#if CONFIG_IDF_TARGET_ESP32C3
RMT.tx_carrier[channel].low = low;
RMT.tx_carrier[channel].high = high;
RMT.rx_conf[channel].conf0.carrier_en = carrier_en;
RMT.rx_conf[channel].conf0.carrier_out_lv = carrier_level;
#else
RMT.carrier_duty_ch[channel].low = low;
RMT.carrier_duty_ch[channel].high = high;
RMT.conf_ch[channel].conf0.carrier_en = carrier_en;
RMT.conf_ch[channel].conf0.carrier_out_lv = carrier_level;
#endif
RMT_MUTEX_UNLOCK(channel);
return true;
@ -183,8 +201,13 @@ bool rmtSetFilter(rmt_obj_t* rmt, bool filter_en, uint32_t filter_level)
RMT_MUTEX_LOCK(channel);
#if CONFIG_IDF_TARGET_ESP32C3
RMT.rx_conf[channel].conf1.rx_filter_thres = filter_level;
RMT.rx_conf[channel].conf1.rx_filter_en = filter_en;
#else
RMT.conf_ch[channel].conf1.rx_filter_thres = filter_level;
RMT.conf_ch[channel].conf1.rx_filter_en = filter_en;
#endif
RMT_MUTEX_UNLOCK(channel);
@ -200,7 +223,11 @@ bool rmtSetRxThreshold(rmt_obj_t* rmt, uint32_t value)
size_t channel = rmt->channel;
RMT_MUTEX_LOCK(channel);
#if CONFIG_IDF_TARGET_ESP32C3
RMT.rx_conf[channel].conf0.idle_thres = value;
#else
RMT.conf_ch[channel].conf0.idle_thres = value;
#endif
RMT_MUTEX_UNLOCK(channel);
return true;
@ -265,7 +292,7 @@ bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
int channel = rmt->channel;
int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers;
if (size > allocated_size) {
if (size > (allocated_size - 1)) {
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
RMT_MUTEX_LOCK(channel);
@ -279,6 +306,18 @@ bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
rmt->intr_mode = E_TX_INTR | E_TXTHR_INTR;
rmt->tx_state = E_SET_CONTI | E_FIRST_HALF;
#if CONFIG_IDF_TARGET_ESP32C3
//uint32_t val = RMT.tx_conf[channel].val;
// init the tx limit for interruption
RMT.tx_lim[channel].limit = half_tx_nr+2;
//RMT.tx_conf[channel].val = val;
//RMT.tx_conf[channel].conf_update = 1;
// reset memory pointer
RMT.tx_conf[channel].mem_rst = 1;
//RMT.tx_conf[channel].mem_rst = 0;
RMT.tx_conf[channel].mem_rd_rst = 1;
//RMT.tx_conf[channel].mem_rd_rst = 0;
#else
// init the tx limit for interruption
RMT.tx_lim_ch[channel].limit = half_tx_nr+2;
// reset memory pointer
@ -288,9 +327,9 @@ bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
RMT.conf_ch[channel].conf1.mem_rd_rst = 0;
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
RMT.conf_ch[channel].conf1.mem_wr_rst = 0;
#endif
// set the tx end mark
RMTMEM.chan[channel].data32[MAX_DATA_PER_ITTERATION].val = 0;
//RMTMEM.chan[channel].data32[MAX_DATA_PER_ITTERATION].val = 0;
// clear and enable both Tx completed and half tx event
RMT.int_clr.val = _INT_TX_END(channel);
@ -304,6 +343,7 @@ bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
RMT_MUTEX_UNLOCK(channel);
// start the transation
//return _rmtSendOnce(rmt, data, MAX_DATA_PER_ITTERATION, true);
return _rmtSendOnce(rmt, data, MAX_DATA_PER_ITTERATION, false);
} else {
// use one-go mode if data fits one buffer
@ -342,10 +382,15 @@ bool rmtBeginReceive(rmt_obj_t* rmt)
RMT.int_clr.val = _INT_ERROR(channel);
RMT.int_ena.val |= _INT_ERROR(channel);
#if CONFIG_IDF_TARGET_ESP32C3
RMT.rx_conf[channel].conf1.mem_owner = 1;
RMT.rx_conf[channel].conf1.mem_wr_rst = 1;
RMT.rx_conf[channel].conf1.rx_en = 1;
#else
RMT.conf_ch[channel].conf1.mem_owner = 1;
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
RMT.conf_ch[channel].conf1.rx_en = 1;
#endif
return true;
}
@ -384,17 +429,26 @@ bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb, void * arg)
rmt->data_alloc = true;
}
#if CONFIG_IDF_TARGET_ESP32C3
RMT.rx_conf[channel].conf1.mem_owner = 1;
#else
RMT.conf_ch[channel].conf1.mem_owner = 1;
#endif
RMT.int_clr.val = _INT_RX_END(channel);
RMT.int_clr.val = _INT_ERROR(channel);
RMT.int_ena.val |= _INT_RX_END(channel);
RMT.int_ena.val |= _INT_ERROR(channel);
#if CONFIG_IDF_TARGET_ESP32C3
RMT.rx_conf[channel].conf1.mem_wr_rst = 1;
RMT.rx_conf[channel].conf1.rx_en = 1;
#else
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
RMT.conf_ch[channel].conf1.rx_en = 1;
#endif
RMT_MUTEX_UNLOCK(channel);
return true;
@ -407,7 +461,11 @@ bool rmtEnd(rmt_obj_t* rmt) {
int channel = rmt->channel;
RMT_MUTEX_LOCK(channel);
#if CONFIG_IDF_TARGET_ESP32C3
RMT.rx_conf[channel].conf1.rx_en = 1;
#else
RMT.conf_ch[channel].conf1.rx_en = 1;
#endif
RMT_MUTEX_UNLOCK(channel);
return true;
@ -437,7 +495,11 @@ bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag
RMT_MUTEX_LOCK(channel);
rmt->intr_mode = E_RX_INTR;
#if CONFIG_IDF_TARGET_ESP32C3
RMT.rx_conf[channel].conf1.mem_owner = 1;
#else
RMT.conf_ch[channel].conf1.mem_owner = 1;
#endif
RMT.int_clr.val = _INT_RX_END(channel);
RMT.int_clr.val = _INT_ERROR(channel);
@ -445,9 +507,15 @@ bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag
RMT.int_ena.val |= _INT_RX_END(channel);
RMT.int_ena.val |= _INT_ERROR(channel);
#if CONFIG_IDF_TARGET_ESP32C3
RMT.rx_conf[channel].conf1.mem_wr_rst = 1;
RMT.rx_conf[channel].conf1.rx_en = 1;
#else
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
RMT.conf_ch[channel].conf1.rx_en = 1;
#endif
RMT_MUTEX_UNLOCK(channel);
// wait for data if requested so
@ -474,14 +542,20 @@ float rmtSetTick(rmt_obj_t* rmt, float tick)
* rmt tick for 1 MHz -> 1us (1x) div_cnt = 0x01
256us (256x) div_cnt = 0x00
*/
int apb_div = _LIMIT(tick/12.5, 256);
int ref_div = _LIMIT(tick/1000, 256);
float apb_tick = 12.5 * apb_div;
float ref_tick = 1000.0 * ref_div;
size_t channel = rmt->channel;
#if CONFIG_IDF_TARGET_ESP32C3
int apb_div = _LIMIT(tick/25.0, 256);
float apb_tick = 25.0 * apb_div;
RMT.tx_conf[channel].div_cnt = apb_div & 0xFF;
RMT.tx_conf[channel].conf_update = 1;
return apb_tick;
#else
int apb_div = _LIMIT(tick/12.5, 256);
int ref_div = _LIMIT(tick/1000, 256);
float apb_tick = 12.5 * apb_div;
float ref_tick = 1000.0 * ref_div;
if (_ABS(apb_tick - tick) < _ABS(ref_tick - tick)) {
RMT.conf_ch[channel].conf0.div_cnt = apb_div & 0xFF;
RMT.conf_ch[channel].conf1.ref_always_on = 1;
@ -491,6 +565,7 @@ float rmtSetTick(rmt_obj_t* rmt, float tick)
RMT.conf_ch[channel].conf1.ref_always_on = 0;
return ref_tick;
}
#endif
}
rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
@ -553,6 +628,47 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
// - no carrier, filter
// - timebase tick of 1us
// - idle threshold set to 0x8000 (max pulse width + 1)
#if CONFIG_IDF_TARGET_ESP32C3
RMT.sys_conf.fifo_mask = 1;
if (tx_not_rx) {
RMT.tx_lim[channel].limit = MAX_DATA_PER_ITTERATION/2 + 2;
RMT.tx_conf[channel].val = 0;
// RMT.tx_conf[channel].carrier_en = 0;
// RMT.tx_conf[channel].carrier_out_lv = 0;
// RMT.tx_conf[channel].tx_conti_mode = 0;
// RMT.tx_conf[channel].idle_out_lv = 0; // signal level for idle
// RMT.tx_conf[channel].tx_start = 0;
// RMT.tx_conf[channel].tx_stop = 0;
// RMT.tx_conf[channel].carrier_eff_en = 0;
// RMT.tx_conf[channel].afifo_rst = 0;
// RMT.tx_conf[channel].conf_update = 0;
// RMT.tx_conf[channel].mem_tx_wrap_en = 0;
// RMT.tx_conf[channel].mem_rst = 1;
RMT.tx_conf[channel].idle_out_en = 1; // enable idle
RMT.tx_conf[channel].div_cnt = 1;
RMT.tx_conf[channel].mem_size = buffers;
RMT.tx_conf[channel].mem_rd_rst = 1;
RMT.tx_conf[channel].conf_update = 1;
} else {
RMT.rx_conf[channel].conf0.div_cnt = 1;
RMT.rx_conf[channel].conf0.mem_size = buffers;
RMT.rx_conf[channel].conf0.carrier_en = 0;
RMT.rx_conf[channel].conf0.carrier_out_lv = 0;
RMT.rx_conf[channel].conf0.idle_thres = 0x80;
RMT.rx_conf[channel].conf1.rx_filter_en = 0;
RMT.rx_conf[channel].conf1.rx_filter_thres = 0;
RMT.rx_conf[channel].conf1.mem_rst = 0;
RMT.rx_conf[channel].conf1.mem_rx_wrap_en = 0;
RMT.rx_conf[channel].conf1.afifo_rst = 0;
RMT.rx_conf[channel].conf1.conf_update = 0;
RMT.rx_conf[channel].conf1.rx_en = 1;
RMT.rx_conf[channel].conf1.mem_owner = 1;
RMT.rx_conf[channel].conf1.mem_wr_rst = 1;
}
#else
RMT.conf_ch[channel].conf0.div_cnt = 1;
RMT.conf_ch[channel].conf0.mem_size = buffers;
RMT.conf_ch[channel].conf0.carrier_en = 0;
@ -585,7 +701,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
RMT.conf_ch[channel].conf1.mem_owner = 1;
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
}
#endif
// install interrupt if at least one channel is active
if (!intr_handle) {
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, _rmt_isr, NULL, &intr_handle);
@ -604,7 +720,11 @@ bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous
return false;
}
int channel = rmt->channel;
#if CONFIG_IDF_TARGET_ESP32C3
RMT.sys_conf.fifo_mask = 1;
#else
RMT.apb_conf.fifo_mask = 1;
#endif
if (data && size>0) {
size_t i;
volatile uint32_t* rmt_mem_ptr = &(RMTMEM.chan[channel].data32[0].val);
@ -616,9 +736,15 @@ bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous
}
RMT_MUTEX_LOCK(channel);
#if CONFIG_IDF_TARGET_ESP32C3
RMT.tx_conf[channel].tx_conti_mode = continuous;
RMT.tx_conf[channel].mem_rd_rst = 1;
RMT.tx_conf[channel].tx_start = 1;
#else
RMT.conf_ch[channel].conf1.tx_conti_mode = continuous;
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
RMT.conf_ch[channel].conf1.tx_start = 1;
#endif
RMT_MUTEX_UNLOCK(channel);
return true;
@ -643,6 +769,7 @@ static void _initPin(int pin, int channel, bool tx_not_rx)
{
if (!periph_enabled) {
periph_enabled = true;
periph_module_reset( PERIPH_RMT_MODULE );
periph_module_enable( PERIPH_RMT_MODULE );
}
if (tx_not_rx) {
@ -658,6 +785,7 @@ static void _initPin(int pin, int channel, bool tx_not_rx)
static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
{
//DEBUG_INTERRUPT_START(4);
int intr_val = RMT.int_st.val;
size_t ch;
for (ch = 0; ch < MAX_CHANNELS; ch++) {
@ -692,9 +820,15 @@ static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
(g_rmt_objects[ch].cb)(data_received, _rmt_get_mem_len(ch), g_rmt_objects[ch].arg);
// restart the reception
#if CONFIG_IDF_TARGET_ESP32C3
RMT.rx_conf[ch].conf1.mem_owner = 1;
RMT.rx_conf[ch].conf1.mem_wr_rst = 1;
RMT.rx_conf[ch].conf1.rx_en = 1;
#else
RMT.conf_ch[ch].conf1.mem_owner = 1;
RMT.conf_ch[ch].conf1.mem_wr_rst = 1;
RMT.conf_ch[ch].conf1.rx_en = 1;
#endif
RMT.int_ena.val |= _INT_RX_END(ch);
} else {
// if not callback provide, expect only one Rx
@ -720,10 +854,17 @@ static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
xEventGroupSetBits(g_rmt_objects[ch].events, RMT_FLAG_ERROR);
}
// reset memory
#if CONFIG_IDF_TARGET_ESP32C3
RMT.tx_conf[ch].mem_rd_rst = 1;
RMT.tx_conf[ch].mem_rd_rst = 0;
RMT.rx_conf[ch].conf1.mem_wr_rst = 1;
RMT.rx_conf[ch].conf1.mem_wr_rst = 0;
#else
RMT.conf_ch[ch].conf1.mem_rd_rst = 1;
RMT.conf_ch[ch].conf1.mem_rd_rst = 0;
RMT.conf_ch[ch].conf1.mem_wr_rst = 1;
RMT.conf_ch[ch].conf1.mem_wr_rst = 0;
#endif
}
if (intr_val & _INT_TX_END(ch)) {
@ -735,15 +876,24 @@ static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
if (intr_val & _INT_THR_EVNT(ch)) {
// clear the flag
RMT.int_clr.val = _INT_THR_EVNT(ch);
#if CONFIG_IDF_TARGET_ESP32C3
//RMT.int_clr.val = _INT_TX_END(ch);
//RMT.int_ena.val |= _INT_TX_END(ch);
#endif
// initial setup of continuous mode
if (g_rmt_objects[ch].tx_state & E_SET_CONTI) {
#if CONFIG_IDF_TARGET_ESP32C3
RMT.tx_conf[ch].tx_conti_mode = 1;
#else
RMT.conf_ch[ch].conf1.tx_conti_mode = 1;
#endif
g_rmt_objects[ch].intr_mode &= ~E_SET_CONTI;
}
_rmt_tx_mem_first(ch);
}
}
//DEBUG_INTERRUPT_END(4);
}
static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch)
@ -753,14 +903,23 @@ static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch)
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
int i;
#if CONFIG_IDF_TARGET_ESP32C3
RMT.tx_lim[ch].limit = half_tx_nr+2;
#else
RMT.tx_lim_ch[ch].limit = half_tx_nr+2;
#endif
RMT.int_clr.val = _INT_THR_EVNT(ch);
RMT.int_ena.val |= _INT_THR_EVNT(ch);
#if CONFIG_IDF_TARGET_ESP32C3
//RMT.int_clr.val = _INT_TX_END(ch);
//RMT.int_ena.val &= ~_INT_TX_END(ch);
#endif
g_rmt_objects[ch].tx_state |= E_FIRST_HALF;
if (data) {
int remaining_size = g_rmt_objects[ch].data_size;
//ets_printf("RMT Tx[%d] %d\n", ch, remaining_size);
// will the remaining data occupy the entire halfbuffer
if (remaining_size > half_tx_nr) {
for (i = 0; i < half_tx_nr; i++) {
@ -779,17 +938,30 @@ static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch)
g_rmt_objects[ch].data_ptr = NULL;
}
#if CONFIG_IDF_TARGET_ESP32C3
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0;
RMT.tx_conf[ch].tx_start = 1;
#endif
} else if ((!(g_rmt_objects[ch].tx_state & E_LAST_DATA)) &&
(!(g_rmt_objects[ch].tx_state & E_END_TRANS))) {
//ets_printf("RMT Tx finishing %d!\n", ch);
for (i = 0; i < half_tx_nr; i++) {
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0x000F000F;
}
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0;
g_rmt_objects[ch].tx_state |= E_LAST_DATA;
#if CONFIG_IDF_TARGET_ESP32C3
RMT.tx_conf[ch].tx_conti_mode = 0;
#else
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
#endif
} else {
log_d("RMT Tx finished %d!\n", ch);
//ets_printf("RMT Tx finished %d!\n", ch);
#if CONFIG_IDF_TARGET_ESP32C3
RMT.tx_conf[ch].tx_conti_mode = 0;
#else
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
#endif
RMT.int_ena.val &= ~_INT_TX_END(ch);
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
g_rmt_objects[ch].intr_mode = E_NO_INTR;
@ -805,10 +977,15 @@ static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch)
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
int i;
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
#if CONFIG_IDF_TARGET_ESP32C3
RMT.tx_lim[ch].limit = 0;
#else
RMT.tx_lim_ch[ch].limit = 0;
#endif
if (data) {
int remaining_size = g_rmt_objects[ch].data_size;
//ets_printf("RMT TxF[%d] %d\n", ch, remaining_size);
// will the remaining data occupy the entire halfbuffer
if (remaining_size > half_tx_nr) {
@ -819,7 +996,11 @@ static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch)
g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF;
// turn off the treshold interrupt
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
#if CONFIG_IDF_TARGET_ESP32C3
RMT.tx_lim[ch].limit = 0;
#else
RMT.tx_lim_ch[ch].limit = 0;
#endif
g_rmt_objects[ch].data_size -= half_tx_nr;
g_rmt_objects[ch].data_ptr += half_tx_nr;
} else {
@ -836,23 +1017,37 @@ static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch)
g_rmt_objects[ch].data_ptr = NULL;
}
} else {
//ets_printf("RMT TxF finished %d!\n", ch);
for (i = 0; i < half_tx_nr; i++) {
RMTMEM.chan[ch].data32[i].val = 0x000F000F;
}
RMTMEM.chan[ch].data32[i].val = 0;
g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF;
#if CONFIG_IDF_TARGET_ESP32C3
RMT.tx_lim[ch].limit = 0;
#else
RMT.tx_lim_ch[ch].limit = 0;
#endif
g_rmt_objects[ch].tx_state |= E_LAST_DATA;
#if CONFIG_IDF_TARGET_ESP32C3
RMT.tx_conf[ch].tx_conti_mode = 0;
#else
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
#endif
}
DEBUG_INTERRUPT_END(2);
}
static int ARDUINO_ISR_ATTR _rmt_get_mem_len(uint8_t channel)
{
#if CONFIG_IDF_TARGET_ESP32C3
int block_num = RMT.rx_conf[channel].conf0.mem_size;
int item_block_len = block_num * 48;
#else
int block_num = RMT.conf_ch[channel].conf0.mem_size;
int item_block_len = block_num * 64;
#endif
volatile rmt_item32_t* data = RMTMEM.chan[channel].data32;
int idx;
for(idx = 0; idx < item_block_len; idx++) {

View File

@ -26,6 +26,8 @@
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/ets_sys.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif

View File

@ -22,19 +22,25 @@
#include "soc/spi_struct.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/dport_reg.h"
#include "soc/rtc.h"
#include "driver/periph_ctrl.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "soc/dport_reg.h"
#include "esp32/rom/ets_sys.h"
#include "esp32/rom/gpio.h"
#include "esp_intr_alloc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "soc/dport_reg.h"
#include "esp32s2/rom/ets_sys.h"
#include "esp32s2/rom/gpio.h"
#include "esp_intr_alloc.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/ets_sys.h"
#include "esp32c3/rom/gpio.h"
#include "esp_intr_alloc.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
@ -62,11 +68,24 @@ struct spi_struct_t {
#define SPI_SPI_SS_IDX(n) ((n==0)?SPICS0_OUT_IDX:((n==1)?SPICS1_OUT_IDX:0))
#define SPI_HSPI_SS_IDX(n) ((n==0)?SPI3_CS0_OUT_IDX:((n==1)?SPI3_CS1_OUT_IDX:((n==2)?SPI3_CS2_OUT_IDX:SPI3_CS0_OUT_IDX)))
#define SPI_FSPI_SS_IDX(n) ((n==0)?FSPICS0_OUT_IDX:((n==1)?FSPICS1_OUT_IDX:((n==2)?FSPICS2_OUT_IDX:VSPICS0_OUT_IDX)))
#define SPI_FSPI_SS_IDX(n) ((n==0)?FSPICS0_OUT_IDX:((n==1)?FSPICS1_OUT_IDX:((n==2)?FSPICS2_OUT_IDX:FSPICS0_OUT_IDX)))
#define SPI_SS_IDX(p, n) ((p==0)?SPI_SPI_SS_IDX(n):((p==1)?SPI_SPI_SS_IDX(n):((p==2)?SPI_HSPI_SS_IDX(n):0)))
#define SPI_INTR_SOURCE(u) ((u==0)?ETS_SPI1_INTR_SOURCE:((u==1)?ETS_SPI2_INTR_SOURCE:((u==2)?ETS_SPI3_INTR_SOURCE:0)))
#elif CONFIG_IDF_TARGET_ESP32C3
// ESP32S2
#define SPI_COUNT (1)
#define SPI_CLK_IDX(p) FSPICLK_OUT_IDX
#define SPI_MISO_IDX(p) FSPIQ_OUT_IDX
#define SPI_MOSI_IDX(p) FSPID_IN_IDX
#define SPI_SPI_SS_IDX(n) ((n==0)?FSPICS0_OUT_IDX:((n==1)?FSPICS1_OUT_IDX:((n==2)?FSPICS2_OUT_IDX:FSPICS0_OUT_IDX)))
#define SPI_SS_IDX(p, n) SPI_SPI_SS_IDX(n)
#define SPI_INTR_SOURCE(u) ETS_SPI2_INTR_SOURCE
#else
// ESP32
#define SPI_COUNT (4)
@ -109,6 +128,8 @@ static spi_t _spi_bus_array[] = {
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 0},
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 1},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 2}
#elif CONFIG_IDF_TARGET_ESP32C3
{(volatile spi_dev_t *)(&GPSPI2), NULL, FSPI}
#else
{(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0},
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1},
@ -131,7 +152,7 @@ void spiAttachSCK(spi_t * spi, int8_t sck)
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
#elif CONFIG_IDF_TARGET_ESP32
if(spi->num == HSPI) {
sck = 14;
} else if(spi->num == VSPI) {
@ -139,6 +160,9 @@ void spiAttachSCK(spi_t * spi, int8_t sck)
} else {
sck = 6;
}
#elif CONFIG_IDF_TARGET_ESP32C3
log_e("SPI Does not have default pins on ESP32C3!");
return;
#endif
}
pinMode(sck, OUTPUT);
@ -158,7 +182,7 @@ void spiAttachMISO(spi_t * spi, int8_t miso)
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
#elif CONFIG_IDF_TARGET_ESP32
if(spi->num == HSPI) {
miso = 12;
} else if(spi->num == VSPI) {
@ -166,6 +190,9 @@ void spiAttachMISO(spi_t * spi, int8_t miso)
} else {
miso = 7;
}
#elif CONFIG_IDF_TARGET_ESP32C3
log_e("SPI Does not have default pins on ESP32C3!");
return;
#endif
}
SPI_MUTEX_LOCK();
@ -187,7 +214,7 @@ void spiAttachMOSI(spi_t * spi, int8_t mosi)
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
#elif CONFIG_IDF_TARGET_ESP32
if(spi->num == HSPI) {
mosi = 13;
} else if(spi->num == VSPI) {
@ -195,6 +222,9 @@ void spiAttachMOSI(spi_t * spi, int8_t mosi)
} else {
mosi = 8;
}
#elif CONFIG_IDF_TARGET_ESP32C3
log_e("SPI Does not have default pins on ESP32C3!");
return;
#endif
}
pinMode(mosi, OUTPUT);
@ -214,7 +244,7 @@ void spiDetachSCK(spi_t * spi, int8_t sck)
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
#elif CONFIG_IDF_TARGET_ESP32
if(spi->num == HSPI) {
sck = 14;
} else if(spi->num == VSPI) {
@ -222,6 +252,9 @@ void spiDetachSCK(spi_t * spi, int8_t sck)
} else {
sck = 6;
}
#elif CONFIG_IDF_TARGET_ESP32C3
log_e("SPI Does not have default pins on ESP32C3!");
return;
#endif
}
pinMatrixOutDetach(sck, false, false);
@ -241,7 +274,7 @@ void spiDetachMISO(spi_t * spi, int8_t miso)
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
#elif CONFIG_IDF_TARGET_ESP32
if(spi->num == HSPI) {
miso = 12;
} else if(spi->num == VSPI) {
@ -249,6 +282,9 @@ void spiDetachMISO(spi_t * spi, int8_t miso)
} else {
miso = 7;
}
#elif CONFIG_IDF_TARGET_ESP32C3
log_e("SPI Does not have default pins on ESP32C3!");
return;
#endif
}
pinMatrixInDetach(SPI_MISO_IDX(spi->num), false, false);
@ -268,7 +304,7 @@ void spiDetachMOSI(spi_t * spi, int8_t mosi)
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
#elif CONFIG_IDF_TARGET_ESP32
if(spi->num == HSPI) {
mosi = 13;
} else if(spi->num == VSPI) {
@ -276,6 +312,9 @@ void spiDetachMOSI(spi_t * spi, int8_t mosi)
} else {
mosi = 8;
}
#elif CONFIG_IDF_TARGET_ESP32C3
log_e("SPI Does not have default pins on ESP32C3!");
return;
#endif
}
pinMatrixOutDetach(mosi, false, false);
@ -299,7 +338,7 @@ void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
#elif CONFIG_IDF_TARGET_ESP32
if(spi->num == HSPI) {
ss = 15;
} else if(spi->num == VSPI) {
@ -307,6 +346,9 @@ void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
} else {
ss = 11;
}
#elif CONFIG_IDF_TARGET_ESP32C3
log_e("SPI Does not have default pins on ESP32C3!");
return;
#endif
}
pinMode(ss, OUTPUT);
@ -327,7 +369,7 @@ void spiDetachSS(spi_t * spi, int8_t ss)
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
#elif CONFIG_IDF_TARGET_ESP32
if(spi->num == HSPI) {
ss = 15;
} else if(spi->num == VSPI) {
@ -335,6 +377,9 @@ void spiDetachSS(spi_t * spi, int8_t ss)
} else {
ss = 11;
}
#elif CONFIG_IDF_TARGET_ESP32C3
log_e("SPI Does not have default pins on ESP32C3!");
return;
#endif
}
pinMatrixOutDetach(ss, false, false);
@ -347,7 +392,7 @@ void spiEnableSSPins(spi_t * spi, uint8_t cs_mask)
return;
}
SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.val &= ~(cs_mask & SPI_CS_MASK_ALL);
#else
spi->dev->pin.val &= ~(cs_mask & SPI_CS_MASK_ALL);
@ -361,7 +406,7 @@ void spiDisableSSPins(spi_t * spi, uint8_t cs_mask)
return;
}
SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.val |= (cs_mask & SPI_CS_MASK_ALL);
#else
spi->dev->pin.val |= (cs_mask & SPI_CS_MASK_ALL);
@ -397,7 +442,7 @@ void spiSSSet(spi_t * spi)
return;
}
SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.cs_keep_active = 1;
#else
spi->dev->pin.cs_keep_active = 1;
@ -411,7 +456,7 @@ void spiSSClear(spi_t * spi)
return;
}
SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.cs_keep_active = 0;
#else
spi->dev->pin.cs_keep_active = 0;
@ -442,7 +487,7 @@ uint8_t spiGetDataMode(spi_t * spi)
if(!spi) {
return 0;
}
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
bool idleEdge = spi->dev->misc.ck_idle_edge;
#else
bool idleEdge = spi->dev->pin.ck_idle_edge;
@ -468,7 +513,7 @@ void spiSetDataMode(spi_t * spi, uint8_t dataMode)
SPI_MUTEX_LOCK();
switch (dataMode) {
case SPI_MODE1:
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
@ -476,7 +521,7 @@ void spiSetDataMode(spi_t * spi, uint8_t dataMode)
spi->dev->user.ck_out_edge = 1;
break;
case SPI_MODE2:
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
@ -484,7 +529,7 @@ void spiSetDataMode(spi_t * spi, uint8_t dataMode)
spi->dev->user.ck_out_edge = 1;
break;
case SPI_MODE3:
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
@ -493,7 +538,7 @@ void spiSetDataMode(spi_t * spi, uint8_t dataMode)
break;
case SPI_MODE0:
default:
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
@ -542,9 +587,11 @@ static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb
static void spiInitBus(spi_t * spi)
{
#ifndef CONFIG_IDF_TARGET_ESP32C3
spi->dev->slave.trans_done = 0;
spi->dev->slave.slave_mode = 0;
#if CONFIG_IDF_TARGET_ESP32S2
#endif
spi->dev->slave.val = 0;
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.val = 0;
#else
spi->dev->pin.val = 0;
@ -552,8 +599,15 @@ static void spiInitBus(spi_t * spi)
spi->dev->user.val = 0;
spi->dev->user1.val = 0;
spi->dev->ctrl.val = 0;
#ifndef CONFIG_IDF_TARGET_ESP32C3
spi->dev->ctrl1.val = 0;
spi->dev->ctrl2.val = 0;
#else
spi->dev->clk_gate.val = 0;
spi->dev->dma_conf.val = 0;
spi->dev->dma_conf.rx_afifo_rst = 1;
spi->dev->dma_conf.buf_afifo_rst = 1;
#endif
spi->dev->clock.val = 0;
}
@ -562,9 +616,9 @@ void spiStopBus(spi_t * spi)
if(!spi) {
return;
}
removeApbChangeCallback(spi, _on_apb_change);
SPI_MUTEX_LOCK();
spiInitBus(spi);
SPI_MUTEX_UNLOCK();
@ -598,7 +652,7 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
}
#else
#elif CONFIG_IDF_TARGET_ESP32
if(spi_num == HSPI) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
@ -609,14 +663,24 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
}
#elif CONFIG_IDF_TARGET_ESP32C3
periph_module_reset( PERIPH_SPI2_MODULE );
periph_module_enable( PERIPH_SPI2_MODULE );
#endif
SPI_MUTEX_LOCK();
spiInitBus(spi);
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->clk_gate.clk_en = 1;
spi->dev->clk_gate.mst_clk_sel = 1;
spi->dev->clk_gate.mst_clk_active = 1;
spi->dev->dma_conf.tx_seg_trans_clr_en = 1;
spi->dev->dma_conf.rx_seg_trans_clr_en = 1;
spi->dev->dma_conf.dma_seg_trans_en = 0;
#endif
spi->dev->user.usr_mosi = 1;
spi->dev->user.usr_miso = 1;
spi->dev->user.doutdin = 1;
int i;
for(i=0; i<16; i++) {
spi->dev->data_buf[i] = 0x00000000;
@ -628,6 +692,7 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
spiSetClockDiv(spi, clockDiv);
addApbChangeCallback(spi, _on_apb_change);
return spi;
}
@ -642,6 +707,11 @@ void spiWaitReady(spi_t * spi)
#if CONFIG_IDF_TARGET_ESP32S2
#define usr_mosi_dbitlen usr_mosi_bit_len
#define usr_miso_dbitlen usr_miso_bit_len
#elif CONFIG_IDF_TARGET_ESP32C3
#define usr_mosi_dbitlen ms_data_bitlen
#define usr_miso_dbitlen ms_data_bitlen
#define mosi_dlen ms_dlen
#define miso_dlen ms_dlen
#endif
void spiWrite(spi_t * spi, const uint32_t *data, uint8_t len)
@ -655,10 +725,16 @@ void spiWrite(spi_t * spi, const uint32_t *data, uint8_t len)
}
SPI_MUTEX_LOCK();
spi->dev->mosi_dlen.usr_mosi_dbitlen = (len * 32) - 1;
#ifndef CONFIG_IDF_TARGET_ESP32C3
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif
for(i=0; i<len; i++) {
spi->dev->data_buf[i] = data[i];
}
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
SPI_MUTEX_UNLOCK();
@ -679,6 +755,10 @@ void spiTransfer(spi_t * spi, uint32_t *data, uint8_t len)
for(i=0; i<len; i++) {
spi->dev->data_buf[i] = data[i];
}
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
for(i=0; i<len; i++) {
@ -694,8 +774,14 @@ void spiWriteByte(spi_t * spi, uint8_t data)
}
SPI_MUTEX_LOCK();
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
#ifndef CONFIG_IDF_TARGET_ESP32C3
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
SPI_MUTEX_UNLOCK();
@ -710,6 +796,10 @@ uint8_t spiTransferByte(spi_t * spi, uint8_t data)
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
spi->dev->miso_dlen.usr_miso_dbitlen = 7;
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
data = spi->dev->data_buf[0] & 0xFF;
@ -737,8 +827,14 @@ void spiWriteWord(spi_t * spi, uint16_t data)
}
SPI_MUTEX_LOCK();
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
#ifndef CONFIG_IDF_TARGET_ESP32C3
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
SPI_MUTEX_UNLOCK();
@ -756,6 +852,10 @@ uint16_t spiTransferWord(spi_t * spi, uint16_t data)
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
spi->dev->miso_dlen.usr_miso_dbitlen = 15;
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
data = spi->dev->data_buf[0];
@ -776,8 +876,14 @@ void spiWriteLong(spi_t * spi, uint32_t data)
}
SPI_MUTEX_LOCK();
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
#ifndef CONFIG_IDF_TARGET_ESP32C3
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
SPI_MUTEX_UNLOCK();
@ -795,6 +901,10 @@ uint32_t spiTransferLong(spi_t * spi, uint32_t data)
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
spi->dev->miso_dlen.usr_miso_dbitlen = 31;
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
data = spi->dev->data_buf[0];
@ -834,6 +944,10 @@ static void __spiTransferBytes(spi_t * spi, const uint8_t * data, uint8_t * out,
spi->dev->data_buf[i] = wordsBuf[i]; //copy buffer to spi fifo
}
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
@ -898,7 +1012,7 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
spi->dev->clock.val = clockDiv;
switch (dataMode) {
case SPI_MODE1:
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
@ -906,7 +1020,7 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
spi->dev->user.ck_out_edge = 1;
break;
case SPI_MODE2:
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
@ -914,7 +1028,7 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
spi->dev->user.ck_out_edge = 1;
break;
case SPI_MODE3:
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
@ -923,7 +1037,7 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
break;
case SPI_MODE0:
default:
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
@ -962,8 +1076,14 @@ void ARDUINO_ISR_ATTR spiWriteByteNL(spi_t * spi, uint8_t data)
return;
}
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
#ifndef CONFIG_IDF_TARGET_ESP32C3
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
}
@ -976,6 +1096,10 @@ uint8_t spiTransferByteNL(spi_t * spi, uint8_t data)
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
spi->dev->miso_dlen.usr_miso_dbitlen = 7;
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
data = spi->dev->data_buf[0] & 0xFF;
@ -991,8 +1115,14 @@ void ARDUINO_ISR_ATTR spiWriteShortNL(spi_t * spi, uint16_t data)
MSB_16_SET(data, data);
}
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
#ifndef CONFIG_IDF_TARGET_ESP32C3
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
}
@ -1008,6 +1138,10 @@ uint16_t spiTransferShortNL(spi_t * spi, uint16_t data)
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
spi->dev->miso_dlen.usr_miso_dbitlen = 15;
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
data = spi->dev->data_buf[0] & 0xFFFF;
@ -1026,8 +1160,14 @@ void ARDUINO_ISR_ATTR spiWriteLongNL(spi_t * spi, uint32_t data)
MSB_32_SET(data, data);
}
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
#ifndef CONFIG_IDF_TARGET_ESP32C3
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
}
@ -1043,6 +1183,10 @@ uint32_t spiTransferLongNL(spi_t * spi, uint32_t data)
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
spi->dev->miso_dlen.usr_miso_dbitlen = 31;
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
data = spi->dev->data_buf[0];
@ -1053,6 +1197,9 @@ uint32_t spiTransferLongNL(spi_t * spi, uint32_t data)
}
void spiWriteNL(spi_t * spi, const void * data_in, uint32_t len){
if(!spi) {
return;
}
size_t longs = len >> 2;
if(len & 3){
longs++;
@ -1065,10 +1212,16 @@ void spiWriteNL(spi_t * spi, const void * data_in, uint32_t len){
c_longs = (longs > 16)?16:longs;
spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1;
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#ifndef CONFIG_IDF_TARGET_ESP32C3
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif
for (int i=0; i<c_longs; i++) {
spi->dev->data_buf[i] = data[i];
}
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
@ -1105,11 +1258,27 @@ void spiTransferBytesNL(spi_t * spi, const void * data_in, uint8_t * data_out, u
spi->dev->data_buf[i] = 0xFFFFFFFF;
}
}
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
if(result){
for (int i=0; i<c_longs; i++) {
result[i] = spi->dev->data_buf[i];
if(c_len & 3){
for (int i=0; i<(c_longs-1); i++) {
result[i] = spi->dev->data_buf[i];
}
uint32_t last_data = spi->dev->data_buf[c_longs-1];
uint8_t * last_out8 = (uint8_t *)&result[c_longs-1];
uint8_t * last_data8 = (uint8_t *)&last_data;
for (int i=0; i<(c_len & 3); i++) {
last_out8[i] = last_data8[i];
}
} else {
for (int i=0; i<c_longs; i++) {
result[i] = spi->dev->data_buf[i];
}
}
}
if(data){
@ -1148,6 +1317,10 @@ void spiTransferBitsNL(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits)
spi->dev->mosi_dlen.usr_mosi_dbitlen = (bits - 1);
spi->dev->miso_dlen.usr_miso_dbitlen = (bits - 1);
spi->dev->data_buf[0] = data;
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
data = spi->dev->data_buf[0];
@ -1180,7 +1353,9 @@ void ARDUINO_ISR_ATTR spiWritePixelsNL(spi_t * spi, const void * data_in, uint32
l_bytes = (c_len & 3);
spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1;
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#ifndef CONFIG_IDF_TARGET_ESP32C3
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
#endif
for (int i=0; i<c_longs; i++) {
if(msb){
if(l_bytes && i == (c_longs - 1)){
@ -1196,6 +1371,10 @@ void ARDUINO_ISR_ATTR spiWritePixelsNL(spi_t * spi, const void * data_in, uint32
spi->dev->data_buf[i] = data[i];
}
}
#if CONFIG_IDF_TARGET_ESP32C3
spi->dev->cmd.update = 1;
while (spi->dev->cmd.update);
#endif
spi->dev->cmd.usr = 1;
while(spi->dev->cmd.usr);
@ -1218,7 +1397,12 @@ typedef union {
uint32_t clkcnt_l: 6; /*it must be equal to spi_clkcnt_N.*/
uint32_t clkcnt_h: 6; /*it must be floor((spi_clkcnt_N+1)/2-1).*/
uint32_t clkcnt_n: 6; /*it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_N+1)*/
#if CONFIG_IDF_TARGET_ESP32C3
uint32_t clkdiv_pre: 4; /*it is pre-divider of spi_clk.*/
uint32_t reserved: 9; /*reserved*/
#else
uint32_t clkdiv_pre: 13; /*it is pre-divider of spi_clk.*/
#endif
uint32_t clk_equ_sysclk: 1; /*1: spi_clk is eqaul to system 0: spi_clk is divided from system clock.*/
};
} spiClk_t;
@ -1260,8 +1444,13 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq)
while(calPreVari++ <= 1) {
calPre = (((apb_freq / (reg.clkcnt_n + 1)) / freq) - 1) + calPreVari;
#if CONFIG_IDF_TARGET_ESP32C3
if(calPre > 0xF) {
reg.clkdiv_pre = 0xF;
#else
if(calPre > 0x1FFF) {
reg.clkdiv_pre = 0x1FFF;
#endif
} else if(calPre <= 0) {
reg.clkdiv_pre = 0;
} else {

View File

@ -25,11 +25,16 @@ extern "C" {
#define SPI_HAS_TRANSACTION
#if CONFIG_IDF_TARGET_ESP32C3
#define FSPI 0
#define HSPI 1
#else
#define FSPI 1 //SPI bus attached to the flash (can use the same data lines but different SS)
#define HSPI 2 //SPI bus normally mapped to pins 12 - 15, but can be matrixed to any pins
#if CONFIG_IDF_TARGET_ESP32
#define VSPI 3 //SPI bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins
#endif
#endif
// This defines are not representing the real Divider of the ESP32
// the Defines match to an AVR Arduino on 16MHz for better compatibility

View File

@ -14,10 +14,12 @@
#include "esp32-hal-timer.h"
#include "freertos/FreeRTOS.h"
#ifndef CONFIG_IDF_TARGET_ESP32C3
#include "freertos/xtensa_api.h"
#include "soc/dport_reg.h"
#endif
#include "freertos/task.h"
#include "soc/timer_group_struct.h"
#include "soc/dport_reg.h"
#include "esp_attr.h"
#include "driver/periph_ctrl.h"
@ -30,6 +32,10 @@
#include "esp32s2/rom/ets_sys.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/ets_sys.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
@ -266,9 +272,6 @@ void timerEnd(hw_timer_t *timer){
}
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
// EDGE DOES NOT WORK CURRENTLY
edge = false;
static bool initialized = false;
static intr_handle_t intr_handle = NULL;
if(intr_handle){
@ -299,12 +302,15 @@ void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
timer->dev->config.level_int_en = edge?0:1;//When set, an alarm will generate a level type interrupt.
timer->dev->config.edge_int_en = edge?1:0;//When set, an alarm will generate an edge type interrupt.
int intr_source = 0;
#ifndef CONFIG_IDF_TARGET_ESP32C3
if(!edge){
#endif
if(timer->group){
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer->timer;
} else {
intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer->timer;
}
#ifndef CONFIG_IDF_TARGET_ESP32C3
} else {
if(timer->group){
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer->timer;
@ -312,6 +318,7 @@ void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer->timer;
}
}
#endif
if(!initialized){
initialized = true;
esp_intr_alloc(intr_source, (int)(ARDUINO_ISR_FLAG|ESP_INTR_FLAG_LOWMED), __timerISR, NULL, &intr_handle);

View File

@ -1,7 +1,8 @@
#include "sdkconfig.h"
#if CONFIG_USB_ENABLED
#if CONFIG_TINYUSB_ENABLED
#include <stdlib.h>
#include <stdbool.h>
#include "esp_log.h"
@ -12,10 +13,14 @@
#include "soc/usb_reg.h"
#include "soc/usb_wrap_reg.h"
#include "soc/usb_wrap_struct.h"
#include "soc/usb_periph.h"
#include "soc/periph_defs.h"
#include "soc/timer_group_struct.h"
#include "soc/system_reg.h"
#include "hal/usb_hal.h"
#include "hal/gpio_ll.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@ -24,8 +29,8 @@
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp_rom_gpio.h"
#include "tinyusb.h"
#include "esp32-hal.h"
#include "esp32-hal-tinyusb.h"
@ -33,6 +38,66 @@
#include "esp32s2/rom/usb/usb_dc.h"
#include "esp32s2/rom/usb/chip_usb_dw_wrapper.h"
typedef enum{
TINYUSB_USBDEV_0,
} tinyusb_usbdev_t;
typedef char *tusb_desc_strarray_device_t[USB_STRING_DESCRIPTOR_ARRAY_SIZE];
typedef struct {
bool external_phy;
} tinyusb_config_t;
static void configure_pins(usb_hal_context_t *usb)
{
for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) {
if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) {
esp_rom_gpio_pad_select_gpio(iopin->pin);
if (iopin->is_output) {
esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false);
} else {
esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false);
if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) {
gpio_ll_input_enable(&GPIO, iopin->pin);
}
}
esp_rom_gpio_pad_unhold(iopin->pin);
}
}
if (!usb->use_external_phy) {
gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
}
}
esp_err_t tinyusb_driver_install(const tinyusb_config_t *config)
{
log_i("Driver installation...");
// Hal init
usb_hal_context_t hal = {
.use_external_phy = config->external_phy
};
usb_hal_init(&hal);
configure_pins(&hal);
if (!tusb_init()) {
log_e("Can't initialize the TinyUSB stack.");
return ESP_FAIL;
}
log_i("Driver installed");
return ESP_OK;
}
typedef char tusb_str_t[127];
static bool WEBUSB_ENABLED = false;
@ -294,9 +359,9 @@ bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const
* Required Callbacks
* */
#if CFG_TUD_HID
__attribute__ ((weak)) const uint8_t * tud_hid_descriptor_report_cb(void){return NULL;}
__attribute__ ((weak)) uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen){return 0;}
__attribute__ ((weak)) void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, const uint8_t * buffer, uint16_t bufsize){}
__attribute__ ((weak)) const uint8_t * tud_hid_descriptor_report_cb(uint8_t itf){return NULL;}
__attribute__ ((weak)) uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen){return 0;}
__attribute__ ((weak)) void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, const uint8_t * buffer, uint16_t bufsize){}
#endif
#if CFG_TUD_MSC
__attribute__ ((weak)) bool tud_msc_test_unit_ready_cb(uint8_t lun){return false;}
@ -385,8 +450,8 @@ static bool tinyusb_load_enabled_interfaces(){
};
memcpy(tinyusb_config_descriptor, descriptor, TUD_CONFIG_DESC_LEN);
if ((tinyusb_loaded_interfaces_mask == (BIT(USB_INTERFACE_CDC) | BIT(USB_INTERFACE_DFU))) || (tinyusb_loaded_interfaces_mask == BIT(USB_INTERFACE_CDC))) {
usb_persist_enabled = true;
log_d("USB Persist enabled");
//usb_persist_enabled = true;
//log_d("USB Persist enabled");
}
log_d("Load Done: if_num: %u, descr_len: %u, if_mask: 0x%x", tinyusb_loaded_interfaces_num, tinyusb_config_descriptor_len, tinyusb_loaded_interfaces_mask);
return true;
@ -465,6 +530,9 @@ static void IRAM_ATTR usb_persist_shutdown_handler(void)
//USB CDC Download
if (usb_persist_enabled) {
chip_usb_set_persist_flags(USBDC_PERSIST_ENA);
} else {
periph_module_reset(PERIPH_USB_MODULE);
periph_module_enable(PERIPH_USB_MODULE);
}
REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
} else if (usb_persist_mode == RESTART_BOOTLOADER_DFU) {
@ -518,11 +586,12 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
bool usb_did_persist = (USB_WRAP.date.val == USBDC_PERSIST_ENA);
if(usb_did_persist && usb_persist_enabled){
//if(usb_did_persist && usb_persist_enabled){
// Enable USB/IO_MUX peripheral reset, if coming from persistent reboot
REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_IO_MUX_RESET_DISABLE);
REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_USB_RESET_DISABLE);
} else {
//} else
if(!usb_did_persist || !usb_persist_enabled){
// Reset USB module
periph_module_reset(PERIPH_USB_MODULE);
periph_module_enable(PERIPH_USB_MODULE);
@ -694,4 +763,4 @@ void usb_dw_reg_dump(void)
}
}
*/
#endif /* CONFIG_USB_ENABLED */
#endif /* CONFIG_TINYUSB_ENABLED */

View File

@ -16,13 +16,18 @@
#include "esp32-hal.h"
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_USB_ENABLED
#if CONFIG_TINYUSB_ENABLED
#ifdef __cplusplus
extern "C" {
#endif
#include "tinyusb.h"
#include "tusb.h"
#include "tusb_option.h"
#include "tusb_config.h"
#define USB_ESPRESSIF_VID 0x303A
#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 10
typedef struct {
uint16_t vid;
@ -46,10 +51,10 @@ typedef struct {
#define TINYUSB_CONFIG_DEFAULT() { \
.vid = USB_ESPRESSIF_VID, \
.pid = 0x0002, \
.product_name = CONFIG_USB_DESC_PRODUCT_STRING, \
.manufacturer_name = CONFIG_USB_DESC_MANUFACTURER_STRING, \
.serial_number = CONFIG_USB_DESC_SERIAL_STRING, \
.fw_version = CONFIG_USB_DESC_BCDDEVICE, \
.product_name = CONFIG_TINYUSB_DESC_PRODUCT_STRING, \
.manufacturer_name = CONFIG_TINYUSB_DESC_MANUFACTURER_STRING, \
.serial_number = CONFIG_TINYUSB_DESC_SERIAL_STRING, \
.fw_version = CONFIG_TINYUSB_DESC_BCDDEVICE, \
.usb_version = 0x0200, \
.usb_class = TUSB_CLASS_MISC, \
.usb_subclass = MISC_SUBCLASS_COMMON, \
@ -99,5 +104,5 @@ uint8_t tinyusb_get_free_out_endpoint(void);
}
#endif
#endif /* CONFIG_USB_ENABLED */
#endif /* CONFIG_TINYUSB_ENABLED */
#endif /* CONFIG_IDF_TARGET_ESP32S2 */

View File

@ -13,13 +13,14 @@
// limitations under the License.
#include "esp32-hal-touch.h"
#ifndef CONFIG_IDF_TARGET_ESP32C3
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_attr.h"
#include "soc/rtc_io_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/touch_sensor.h"
#include "esp_system.h"
@ -225,3 +226,4 @@ void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t thresh
extern uint16_t touchRead(uint8_t pin) __attribute__ ((weak, alias("__touchRead")));
extern void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold) __attribute__ ((weak, alias("__touchAttachInterrupt")));
extern void touchSetCycles(uint16_t measure, uint16_t sleep) __attribute__ ((weak, alias("__touchSetCycles")));
#endif

View File

@ -23,19 +23,25 @@
#include "soc/uart_struct.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/dport_reg.h"
#include "soc/rtc.h"
#include "hal/uart_ll.h"
#include "esp_intr_alloc.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "soc/dport_reg.h"
#include "esp32/rom/ets_sys.h"
#include "esp32/rom/uart.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "soc/dport_reg.h"
#include "esp32s2/rom/ets_sys.h"
#include "esp32s2/rom/uart.h"
#include "soc/periph_defs.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/ets_sys.h"
#include "esp32c3/rom/uart.h"
#include "soc/periph_defs.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
@ -45,18 +51,24 @@
#include "esp_intr.h"
#endif
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32
#define UART_PORTS_NUM 3
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:( (u==2)?DR_REG_UART2_BASE:0)))
#define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:( (u==2)?U2RXD_IN_IDX:0)))
#define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:( (u==2)?U2TXD_OUT_IDX:0)))
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:((u==2)?ETS_UART2_INTR_SOURCE:0)))
#elif CONFIG_IDF_TARGET_ESP32S2
#define UART_PORTS_NUM 2
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:0))
#define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:0))
#define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:0))
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:0))
#else
#define UART_PORTS_NUM 3
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:( (u==2)?DR_REG_UART2_BASE:0)))
#define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:( (u==2)?U2RXD_IN_IDX:0)))
#define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:( (u==2)?U2TXD_OUT_IDX:0)))
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:((u==2)?ETS_UART2_INTR_SOURCE:0)))
#define UART_PORTS_NUM 2
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:0))
#define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:0))
#define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:0))
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:0))
#endif
static int s_uart_debug_nr = 0;
@ -130,10 +142,10 @@ static void ARDUINO_ISR_ATTR _uart_isr(void *arg)
}
}
void uartEnableInterrupt(uart_t* uart)
static void uartEnableInterrupt(uart_t* uart, uint8_t rxfifo_full_thrhd)
{
UART_MUTEX_LOCK();
uart->dev->conf1.rxfifo_full_thrhd = 112;
uart->dev->conf1.rxfifo_full_thrhd = rxfifo_full_thrhd;
#if CONFIG_IDF_TARGET_ESP32
uart->dev->conf1.rx_tout_thrhd = 2;
#else
@ -149,7 +161,7 @@ void uartEnableInterrupt(uart_t* uart)
UART_MUTEX_UNLOCK();
}
void uartDisableInterrupt(uart_t* uart)
static void uartDisableInterrupt(uart_t* uart)
{
UART_MUTEX_LOCK();
uart->dev->conf1.val = 0;
@ -162,7 +174,7 @@ void uartDisableInterrupt(uart_t* uart)
UART_MUTEX_UNLOCK();
}
void uartDetachRx(uart_t* uart, uint8_t rxPin)
static void uartDetachRx(uart_t* uart, uint8_t rxPin)
{
if(uart == NULL) {
return;
@ -171,7 +183,7 @@ void uartDetachRx(uart_t* uart, uint8_t rxPin)
uartDisableInterrupt(uart);
}
void uartDetachTx(uart_t* uart, uint8_t txPin)
static void uartDetachTx(uart_t* uart, uint8_t txPin)
{
if(uart == NULL) {
return;
@ -179,17 +191,17 @@ void uartDetachTx(uart_t* uart, uint8_t txPin)
pinMatrixOutDetach(txPin, false, false);
}
void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted)
static void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted, uint8_t rxfifo_full_thrhd)
{
if(uart == NULL || rxPin >= GPIO_PIN_COUNT) {
return;
}
pinMode(rxPin, INPUT);
uartEnableInterrupt(uart);
uartEnableInterrupt(uart, rxfifo_full_thrhd);
pinMatrixInAttach(rxPin, UART_RXD_IDX(uart->num), inverted);
}
void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
static void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
{
if(uart == NULL || txPin >= GPIO_PIN_COUNT) {
return;
@ -198,7 +210,7 @@ void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
pinMatrixOutAttach(txPin, UART_TXD_IDX(uart->num), inverted, false);
}
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted)
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted, uint8_t rxfifo_full_thrhd)
{
if(uart_nr >= UART_PORTS_NUM) {
return NULL;
@ -225,6 +237,9 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
return NULL;
}
}
#if CONFIG_IDF_TARGET_ESP32C3
#else
if(uart_nr == 1){
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST);
@ -237,6 +252,7 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST);
}
#endif
uartFlush(uart);
uartSetBaudRate(uart, baudrate);
UART_MUTEX_LOCK();
@ -256,7 +272,7 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
UART_MUTEX_UNLOCK();
if(rxPin != -1) {
uartAttachRx(uart, rxPin, inverted);
uartAttachRx(uart, rxPin, inverted, rxfifo_full_thrhd);
}
if(txPin != -1) {
@ -322,7 +338,11 @@ uint32_t uartAvailable(uart_t* uart)
if(uart == NULL || uart->queue == NULL) {
return 0;
}
#ifdef UART_READ_RX_FIFO
return (uxQueueMessagesWaiting(uart->queue) + uart->dev->status.rxfifo_cnt) ;
#else
return uxQueueMessagesWaiting(uart->queue);
#endif
}
uint32_t uartAvailableForWrite(uart_t* uart)
@ -333,6 +353,7 @@ uint32_t uartAvailableForWrite(uart_t* uart)
return 0x7f - uart->dev->status.txfifo_cnt;
}
#ifdef UART_READ_RX_FIFO
void uartRxFifoToQueue(uart_t* uart)
{
uint8_t c;
@ -357,6 +378,7 @@ void uartRxFifoToQueue(uart_t* uart)
uart->dev->int_clr.val = 0xffffffff;
UART_MUTEX_UNLOCK();
}
#endif
uint8_t uartRead(uart_t* uart)
{
@ -364,10 +386,12 @@ uint8_t uartRead(uart_t* uart)
return 0;
}
uint8_t c;
#ifdef UART_READ_RX_FIFO
if ((uxQueueMessagesWaiting(uart->queue) == 0) && (uart->dev->status.rxfifo_cnt > 0))
{
uartRxFifoToQueue(uart);
}
#endif
if(xQueueReceive(uart->queue, &c, 0)) {
return c;
}
@ -380,10 +404,12 @@ uint8_t uartPeek(uart_t* uart)
return 0;
}
uint8_t c;
#ifdef UART_READ_RX_FIFO
if ((uxQueueMessagesWaiting(uart->queue) == 0) && (uart->dev->status.rxfifo_cnt > 0))
{
uartRxFifoToQueue(uart);
}
#endif
if(xQueuePeek(uart->queue, &c, 0)) {
return c;
}
@ -467,9 +493,7 @@ void uartSetBaudRate(uart_t* uart, uint32_t baud_rate)
return;
}
UART_MUTEX_LOCK();
uint32_t clk_div = ((getApbFrequency()<<4)/baud_rate);
uart->dev->clk_div.div_int = clk_div>>4 ;
uart->dev->clk_div.div_frag = clk_div & 0xf;
uart_ll_set_baudrate(uart->dev, baud_rate);
UART_MUTEX_UNLOCK();
}
@ -666,15 +690,17 @@ unsigned long uartBaudrateDetect(uart_t *uart, bool flg)
*/
void uartStartDetectBaudrate(uart_t *uart) {
if(!uart) return;
#ifndef CONFIG_IDF_TARGET_ESP32C3
uart->dev->auto_baud.glitch_filt = 0x08;
uart->dev->auto_baud.en = 0;
uart->dev->auto_baud.en = 1;
#endif
}
unsigned long
uartDetectBaudrate(uart_t *uart)
{
#ifndef CONFIG_IDF_TARGET_ESP32C3
static bool uartStateDetectingBaudrate = false;
if(!uartStateDetectingBaudrate) {
@ -709,6 +735,9 @@ uartDetectBaudrate(uart_t *uart)
}
return default_rates[i];
#else
return 0;
#endif
}
/*

View File

@ -51,7 +51,7 @@ extern "C" {
struct uart_struct_t;
typedef struct uart_struct_t uart_t;
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted);
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted, uint8_t rxfifo_full_thrhd);
void uartEnd(uart_t* uart, uint8_t rxPin, uint8_t txPin);
uint32_t uartAvailable(uart_t* uart);

View File

@ -6,6 +6,10 @@
#include "USB.h"
#endif
#ifndef CONFIG_ARDUINO_LOOP_STACK_SIZE
#define CONFIG_ARDUINO_LOOP_STACK_SIZE 8192
#endif
TaskHandle_t loopTaskHandle = NULL;
#if CONFIG_AUTOSTART_ARDUINO
@ -44,7 +48,7 @@ extern "C" void app_main()
#endif
loopTaskWDTEnabled = false;
initArduino();
xTaskCreateUniversal(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
xTaskCreateUniversal(loopTask, "loopTask", CONFIG_ARDUINO_LOOP_STACK_SIZE, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
}
#endif

View File

@ -8,8 +8,8 @@ Installation instructions for Debian / Ubuntu OS
sudo usermod -a -G dialout $USER && \
sudo apt-get install git && \
wget https://bootstrap.pypa.io/get-pip.py && \
sudo python get-pip.py && \
sudo pip install pyserial && \
sudo python3 get-pip.py && \
sudo pip3 install pyserial && \
mkdir -p ~/Arduino/hardware/espressif && \
cd ~/Arduino/hardware/espressif && \
git clone https://github.com/espressif/arduino-esp32.git esp32 && \

BIN
docs/esp32s2_pinmap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 KiB

View File

@ -277,6 +277,22 @@ void AsyncUDPMessage::flush()
_index = 0;
}
AsyncUDPPacket::AsyncUDPPacket(AsyncUDPPacket &packet){
_udp = packet._udp;
_pb = packet._pb;
_if = packet._if;
_data = packet._data;
_len = packet._len;
_index = 0;
memcpy(&_remoteIp, &packet._remoteIp, sizeof(ip_addr_t));
memcpy(&_localIp, &packet._localIp, sizeof(ip_addr_t));
_localPort = packet._localPort;
_remotePort = packet._remotePort;
memcpy(_remoteMac, packet._remoteMac, 6);
pbuf_ref(_pb);
}
AsyncUDPPacket::AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *raddr, uint16_t rport, struct netif * ntif)
{
@ -294,18 +310,18 @@ AsyncUDPPacket::AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *raddr,
_localIp.type = _remoteIp.type;
eth_hdr* eth = NULL;
udp_hdr* udphdr = reinterpret_cast<udp_hdr*>(_data - UDP_HLEN);
udp_hdr* udphdr = (udp_hdr *)(_data - UDP_HLEN);
_localPort = ntohs(udphdr->dest);
_remotePort = ntohs(udphdr->src);
if (_remoteIp.type == IPADDR_TYPE_V4) {
eth = (eth_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP_HLEN - SIZEOF_ETH_HDR);
struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP_HLEN);
eth = (eth_hdr *)(_data - UDP_HLEN - IP_HLEN - SIZEOF_ETH_HDR);
struct ip_hdr * iphdr = (struct ip_hdr *)(_data - UDP_HLEN - IP_HLEN);
_localIp.u_addr.ip4.addr = iphdr->dest.addr;
_remoteIp.u_addr.ip4.addr = iphdr->src.addr;
} else {
eth = (eth_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP6_HLEN - SIZEOF_ETH_HDR);
struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP6_HLEN);
eth = (eth_hdr *)(_data - UDP_HLEN - IP6_HLEN - SIZEOF_ETH_HDR);
struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(_data - UDP_HLEN - IP6_HLEN);
memcpy(&_localIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16);
memcpy(&_remoteIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->src.addr, 16);
}
@ -479,6 +495,7 @@ AsyncUDP::AsyncUDP()
{
_pcb = NULL;
_connected = false;
_lastErr = ERR_OK;
_handler = NULL;
}
@ -517,8 +534,8 @@ bool AsyncUDP::connect(const ip_addr_t *addr, uint16_t port)
}
close();
UDP_MUTEX_LOCK();
err_t err = _udp_connect(_pcb, addr, port);
if(err != ERR_OK) {
_lastErr = _udp_connect(_pcb, addr, port);
if(_lastErr != ERR_OK) {
UDP_MUTEX_UNLOCK();
return false;
}
@ -646,7 +663,7 @@ size_t AsyncUDP::writeTo(const uint8_t * data, size_t len, const ip_addr_t * add
if(len > CONFIG_TCP_MSS) {
len = CONFIG_TCP_MSS;
}
err_t err = ERR_OK;
_lastErr = ERR_OK;
pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if(pbt != NULL) {
uint8_t* dst = reinterpret_cast<uint8_t*>(pbt->payload);
@ -656,16 +673,16 @@ size_t AsyncUDP::writeTo(const uint8_t * data, size_t len, const ip_addr_t * add
void * nif = NULL;
tcpip_adapter_get_netif((tcpip_adapter_if_t)tcpip_if, &nif);
if(!nif){
err = _udp_sendto(_pcb, pbt, addr, port);
_lastErr = _udp_sendto(_pcb, pbt, addr, port);
} else {
err = _udp_sendto_if(_pcb, pbt, addr, port, (struct netif *)nif);
_lastErr = _udp_sendto_if(_pcb, pbt, addr, port, (struct netif *)nif);
}
} else {
err = _udp_sendto(_pcb, pbt, addr, port);
_lastErr = _udp_sendto(_pcb, pbt, addr, port);
}
UDP_MUTEX_UNLOCK();
pbuf_free(pbt);
if(err < ERR_OK) {
if(_lastErr < ERR_OK) {
return 0;
}
return len;
@ -682,9 +699,8 @@ void AsyncUDP::_recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t po
if(_handler) {
AsyncUDPPacket packet(this, this_pb, addr, port, netif);
_handler(packet);
} else {
pbuf_free(this_pb);
}
pbuf_free(this_pb);
}
}
@ -870,6 +886,10 @@ bool AsyncUDP::connected()
return _connected;
}
esp_err_t AsyncUDP::lastErr() {
return _lastErr;
}
void AsyncUDP::onPacket(AuPacketHandlerFunctionWithArg cb, void * arg)
{
onPacket(std::bind(cb, arg, std::placeholders::_1));

View File

@ -58,6 +58,7 @@ protected:
size_t _len;
size_t _index;
public:
AsyncUDPPacket(AsyncUDPPacket &packet);
AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif * netif);
virtual ~AsyncUDPPacket();
@ -95,6 +96,7 @@ protected:
udp_pcb *_pcb;
//xSemaphoreHandle _lock;
bool _connected;
esp_err_t _lastErr;
AuPacketHandlerFunction _handler;
bool _init();
@ -144,6 +146,7 @@ public:
IPAddress listenIP();
IPv6Address listenIPv6();
bool connected();
esp_err_t lastErr();
operator bool();
static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, const ip_addr_t *addr, uint16_t port, struct netif * netif);

View File

@ -59,14 +59,37 @@ BLEAddress::BLEAddress(std::string stringAddress) {
* @return True if the addresses are equal.
*/
bool BLEAddress::equals(BLEAddress otherAddress) {
return memcmp(otherAddress.getNative(), m_address, 6) == 0;
return memcmp(otherAddress.getNative(), m_address, ESP_BD_ADDR_LEN) == 0;
} // equals
bool BLEAddress::operator==(const BLEAddress& otherAddress) const {
return memcmp(otherAddress.m_address, m_address, ESP_BD_ADDR_LEN) == 0;
}
bool BLEAddress::operator!=(const BLEAddress& otherAddress) const {
return !(*this == otherAddress);
}
bool BLEAddress::operator<(const BLEAddress& otherAddress) const {
return memcmp(otherAddress.m_address, m_address, ESP_BD_ADDR_LEN) < 0;
}
bool BLEAddress::operator<=(const BLEAddress& otherAddress) const {
return !(*this > otherAddress);
}
bool BLEAddress::operator>=(const BLEAddress& otherAddress) const {
return !(*this < otherAddress);
}
bool BLEAddress::operator>(const BLEAddress& otherAddress) const {
return memcmp(otherAddress.m_address, m_address, ESP_BD_ADDR_LEN) > 0;
}
/**
* @brief Return the native representation of the address.
* @return The native representation of the address.
*/
*/
esp_bd_addr_t *BLEAddress::getNative() {
return &m_address;
} // getNative

View File

@ -23,6 +23,12 @@ public:
BLEAddress(esp_bd_addr_t address);
BLEAddress(std::string stringAddress);
bool equals(BLEAddress otherAddress);
bool operator==(const BLEAddress& otherAddress) const;
bool operator!=(const BLEAddress& otherAddress) const;
bool operator<(const BLEAddress& otherAddress) const;
bool operator<=(const BLEAddress& otherAddress) const;
bool operator>(const BLEAddress& otherAddress) const;
bool operator>=(const BLEAddress& otherAddress) const;
esp_bd_addr_t* getNative();
std::string toString();

View File

@ -25,6 +25,7 @@ BLEAdvertisedDevice::BLEAdvertisedDevice() {
m_manufacturerData = "";
m_name = "";
m_rssi = -9999;
m_serviceUUIDs = {};
m_serviceData = {};
m_serviceDataUUIDs = {};
m_txPower = 0;
@ -34,8 +35,6 @@ BLEAdvertisedDevice::BLEAdvertisedDevice() {
m_haveManufacturerData = false;
m_haveName = false;
m_haveRSSI = false;
m_haveServiceData = false;
m_haveServiceUUID = false;
m_haveTXPower = false;
} // BLEAdvertisedDevice
@ -107,11 +106,7 @@ BLEScan* BLEAdvertisedDevice::getScan() {
* @return Number of service data discovered.
*/
int BLEAdvertisedDevice::getServiceDataCount() {
if (m_haveServiceData)
return m_serviceData.size();
else
return 0;
return m_serviceData.size();
} //getServiceDataCount
/**
@ -119,7 +114,7 @@ int BLEAdvertisedDevice::getServiceDataCount() {
* @return The ServiceData of the advertised device.
*/
std::string BLEAdvertisedDevice::getServiceData() {
return m_serviceData[0];
return m_serviceData.empty() ? std::string() : m_serviceData.front();
} //getServiceData
/**
@ -130,12 +125,20 @@ std::string BLEAdvertisedDevice::getServiceData(int i) {
return m_serviceData[i];
} //getServiceData
/**
* @brief Get the number of service data UUIDs.
* @return Number of service data UUIDs discovered.
*/
int BLEAdvertisedDevice::getServiceDataUUIDCount() {
return m_serviceDataUUIDs.size();
} //getServiceDataUUIDCount
/**
* @brief Get the service data UUID.
* @return The service data UUID.
*/
BLEUUID BLEAdvertisedDevice::getServiceDataUUID() {
return m_serviceDataUUIDs[0];
return m_serviceDataUUIDs.empty() ? BLEUUID() : m_serviceDataUUIDs.front();
} // getServiceDataUUID
/**
@ -146,12 +149,20 @@ BLEUUID BLEAdvertisedDevice::getServiceDataUUID(int i) {
return m_serviceDataUUIDs[i];
} // getServiceDataUUID
/**
* @brief Get the number of service UUIDs.
* @return Number of service UUIDs discovered.
*/
int BLEAdvertisedDevice::getServiceUUIDCount() {
return m_serviceUUIDs.size();
} //getServiceUUIDCount
/**
* @brief Get the Service UUID.
* @return The Service UUID of the advertised device.
*/
BLEUUID BLEAdvertisedDevice::getServiceUUID() {
return m_serviceUUIDs[0];
return m_serviceUUIDs.empty() ? BLEUUID() : m_serviceUUIDs.front();
} // getServiceUUID
/**
@ -167,7 +178,7 @@ BLEUUID BLEAdvertisedDevice::getServiceUUID(int i) {
* @return Return true if service is advertised
*/
bool BLEAdvertisedDevice::isAdvertisingService(BLEUUID uuid){
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
for (int i = 0; i < getServiceUUIDCount(); i++) {
if (m_serviceUUIDs[i].equals(uuid)) return true;
}
return false;
@ -224,7 +235,7 @@ bool BLEAdvertisedDevice::haveRSSI() {
* @return True if there is a service data value present.
*/
bool BLEAdvertisedDevice::haveServiceData() {
return m_haveServiceData;
return !m_serviceData.empty();
} // haveServiceData
@ -233,7 +244,7 @@ bool BLEAdvertisedDevice::haveServiceData() {
* @return True if there is a service UUID value present.
*/
bool BLEAdvertisedDevice::haveServiceUUID() {
return m_haveServiceUUID;
return !m_serviceUUIDs.empty();
} // haveServiceUUID
@ -486,7 +497,6 @@ void BLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
*/
void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) {
m_serviceUUIDs.push_back(serviceUUID);
m_haveServiceUUID = true;
log_d("- addServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str());
} // setServiceUUID
@ -496,7 +506,6 @@ void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) {
* @param [in] data ServiceData value.
*/
void BLEAdvertisedDevice::setServiceData(std::string serviceData) {
m_haveServiceData = true; // Set the flag that indicates we have service data.
m_serviceData.push_back(serviceData); // Save the service data that we received.
} //setServiceData
@ -506,7 +515,6 @@ void BLEAdvertisedDevice::setServiceData(std::string serviceData) {
* @param [in] data ServiceDataUUID value.
*/
void BLEAdvertisedDevice::setServiceDataUUID(BLEUUID uuid) {
m_haveServiceData = true; // Set the flag that indicates we have service data.
m_serviceDataUUIDs.push_back(uuid);
log_d("- addServiceDataUUID(): serviceDataUUID: %s", uuid.toString().c_str());
} // setServiceDataUUID
@ -542,7 +550,7 @@ std::string BLEAdvertisedDevice::toString() {
free(pHex);
}
if (haveServiceUUID()) {
for (int i=0; i < m_serviceUUIDs.size(); i++) {
for (int i=0; i < getServiceUUIDCount(); i++) {
res += ", serviceUUID: " + getServiceUUID(i).toString();
}
}

View File

@ -42,6 +42,8 @@ public:
BLEUUID getServiceUUID();
BLEUUID getServiceUUID(int i);
int getServiceDataCount();
int getServiceDataUUIDCount();
int getServiceUUIDCount();
int8_t getTXPower();
uint8_t* getPayload();
size_t getPayloadLength();
@ -83,8 +85,6 @@ private:
bool m_haveManufacturerData;
bool m_haveName;
bool m_haveRSSI;
bool m_haveServiceData;
bool m_haveServiceUUID;
bool m_haveTXPower;

View File

@ -91,6 +91,10 @@ void BLEAdvertising::setAdvertisementType(esp_ble_adv_type_t adv_type){
m_advParams.adv_type = adv_type;
} // setAdvertisementType
void BLEAdvertising::setAdvertisementChannelMap(esp_ble_adv_channel_t channel_map) {
m_advParams.channel_map = channel_map;
} // setAdvertisementChannelMap
void BLEAdvertising::setMinInterval(uint16_t mininterval) {
m_advParams.adv_int_min = mininterval;
} // setMinInterval

View File

@ -53,6 +53,7 @@ public:
void stop();
void setAppearance(uint16_t appearance);
void setAdvertisementType(esp_ble_adv_type_t adv_type);
void setAdvertisementChannelMap(esp_ble_adv_channel_t channel_map);
void setMaxInterval(uint16_t maxinterval);
void setMinInterval(uint16_t mininterval);
void setAdvertisementData(BLEAdvertisementData& advertisementData);

View File

@ -223,7 +223,8 @@ void BLECharacteristic::handleGATTServerEvent(
m_writeEvt = false;
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
m_value.commit();
m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
// Invoke the onWrite callback handler.
m_pCallbacks->onWrite(this, param);
} else {
m_value.cancel();
}
@ -311,7 +312,8 @@ void BLECharacteristic::handleGATTServerEvent(
} // Response needed
if (param->write.is_prep != true) {
m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
// Invoke the onWrite callback handler.
m_pCallbacks->onWrite(this, param);
}
} // Match on handles.
break;
@ -383,7 +385,7 @@ void BLECharacteristic::handleGATTServerEvent(
// If is.long is false then this is the first (or only) request to read data, so invoke the callback
// Invoke the read callback.
m_pCallbacks->onRead(this);
m_pCallbacks->onRead(this, param);
std::string value = m_value.getValue();
@ -757,46 +759,35 @@ std::string BLECharacteristic::toString() {
BLECharacteristicCallbacks::~BLECharacteristicCallbacks() {}
void BLECharacteristicCallbacks::onRead(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param) {
onRead(pCharacteristic);
} // onRead
/**
* @brief Callback function to support a read request.
* @param [in] pCharacteristic The characteristic that is the source of the event.
*/
void BLECharacteristicCallbacks::onRead(BLECharacteristic* pCharacteristic) {
log_d("BLECharacteristicCallbacks", ">> onRead: default");
log_d("BLECharacteristicCallbacks", "<< onRead");
log_d(">> onRead: default");
log_d("<< onRead");
} // onRead
/**
* @brief Callback function to support a write request.
* @param [in] pCharacteristic The characteristic that is the source of the event.
*/
void BLECharacteristicCallbacks::onWrite(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param) {
onWrite(pCharacteristic);
} // onWrite
void BLECharacteristicCallbacks::onWrite(BLECharacteristic* pCharacteristic) {
log_d("BLECharacteristicCallbacks", ">> onWrite: default");
log_d("BLECharacteristicCallbacks", "<< onWrite");
log_d(">> onWrite: default");
log_d("<< onWrite");
} // onWrite
/**
* @brief Callback function to support a Notify request.
* @param [in] pCharacteristic The characteristic that is the source of the event.
*/
void BLECharacteristicCallbacks::onNotify(BLECharacteristic* pCharacteristic) {
log_d("BLECharacteristicCallbacks", ">> onNotify: default");
log_d("BLECharacteristicCallbacks", "<< onNotify");
log_d(">> onNotify: default");
log_d("<< onNotify");
} // onNotify
/**
* @brief Callback function to support a Notify/Indicate Status report.
* @param [in] pCharacteristic The characteristic that is the source of the event.
* @param [in] s Status of the notification/indication
* @param [in] code Additional code of underlying errors
*/
void BLECharacteristicCallbacks::onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code) {
log_d("BLECharacteristicCallbacks", ">> onStatus: default");
log_d("BLECharacteristicCallbacks", "<< onStatus");
log_d(">> onStatus: default");
log_d("<< onStatus");
} // onStatus

View File

@ -145,9 +145,43 @@ public:
}Status;
virtual ~BLECharacteristicCallbacks();
/**
* @brief Callback function to support a read request.
* @param [in] pCharacteristic The characteristic that is the source of the event.
* @param [in] param The BLE GATTS param. Use param->read.
*/
virtual void onRead(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param);
/**
* @brief DEPRECATED! Callback function to support a read request. Called only if onRead(,) not overrided.
* @param [in] pCharacteristic The characteristic that is the source of the event.
*/
virtual void onRead(BLECharacteristic* pCharacteristic);
/**
* @brief Callback function to support a write request.
* @param [in] pCharacteristic The characteristic that is the source of the event.
* @param [in] param The BLE GATTS param. Use param->write.
*/
virtual void onWrite(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param);
/**
* @brief DEPRECATED! Callback function to support a write request. Called only if onWrite(,) not overrided.
* @param [in] pCharacteristic The characteristic that is the source of the event.
*/
virtual void onWrite(BLECharacteristic* pCharacteristic);
/**
* @brief Callback function to support a Notify request.
* @param [in] pCharacteristic The characteristic that is the source of the event.
*/
virtual void onNotify(BLECharacteristic* pCharacteristic);
/**
* @brief Callback function to support a Notify/Indicate Status report.
* @param [in] pCharacteristic The characteristic that is the source of the event.
* @param [in] s Status of the notification/indication
* @param [in] code Additional code of underlying errors
*/
virtual void onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code);
};
#endif /* CONFIG_BLUEDROID_ENABLED */

View File

@ -10,6 +10,7 @@
#include <esp_bt_main.h>
#include <esp_gap_ble_api.h>
#include <esp_gattc_api.h>
#include <esp_gatt_common_api.h>// ESP32 BLE
#include "BLEClient.h"
#include "BLEUtils.h"
#include "BLEService.h"
@ -60,6 +61,7 @@ BLEClient::~BLEClient() {
delete myPair.second;
}
m_servicesMap.clear();
m_servicesMapByInstID.clear();
} // ~BLEClient
@ -109,7 +111,17 @@ bool BLEClient::connect(BLEAddress address, esp_ble_addr_type_t type) {
return false;
}
m_semaphoreRegEvt.wait("connect");
uint32_t rc = m_semaphoreRegEvt.wait("connect");
if (rc != ESP_GATT_OK) {
// fixes ESP_GATT_NO_RESOURCES error mostly
log_e("esp_ble_gattc_app_register_error: rc=%d", rc);
BLEDevice::removePeerDevice(m_appId, true);
// not sure if this is needed here
// esp_ble_gattc_app_unregister(m_gattc_if);
// m_gattc_if = ESP_GATT_IF_NONE;
return false;
}
m_peerAddress = address;
@ -127,7 +139,13 @@ bool BLEClient::connect(BLEAddress address, esp_ble_addr_type_t type) {
return false;
}
uint32_t rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete.
rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete.
// check the status of the connection and cleanup in case of failure
if (rc != ESP_GATT_OK) {
BLEDevice::removePeerDevice(m_appId, true);
esp_ble_gattc_app_unregister(m_gattc_if);
m_gattc_if = ESP_GATT_IF_NONE;
}
log_v("<< connect(), rc=%d", rc==ESP_GATT_OK);
return rc == ESP_GATT_OK;
} // connect
@ -159,6 +177,11 @@ void BLEClient::gattClientEventHandler(
log_d("gattClientEventHandler [esp_gatt_if: %d] ... %s",
gattc_if, BLEUtils::gattClientEventTypeToString(event).c_str());
// it is possible to receive events from other connections while waiting for registration
if (m_gattc_if == ESP_GATT_IF_NONE && event != ESP_GATTC_REG_EVT) {
return;
}
// Execute handler code based on the type of event received.
switch(event) {
@ -183,15 +206,17 @@ void BLEClient::gattClientEventHandler(
if (evtParam->disconnect.conn_id != getConnId()) break;
// If we receive a disconnect event, set the class flag that indicates that we are
// no longer connected.
if (m_isConnected && m_pClientCallbacks != nullptr) {
m_pClientCallbacks->onDisconnect(this);
}
bool m_wasConnected = m_isConnected;
m_isConnected = false;
esp_ble_gattc_app_unregister(m_gattc_if);
m_gattc_if = ESP_GATT_IF_NONE;
m_semaphoreOpenEvt.give(ESP_GATT_IF_NONE);
m_semaphoreRssiCmplEvt.give();
m_semaphoreSearchCmplEvt.give(1);
BLEDevice::removePeerDevice(m_appId, true);
if (m_wasConnected && m_pClientCallbacks != nullptr) {
m_pClientCallbacks->onDisconnect(this);
}
break;
} // ESP_GATTC_DISCONNECT_EVT
@ -227,7 +252,8 @@ void BLEClient::gattClientEventHandler(
//
case ESP_GATTC_REG_EVT: {
m_gattc_if = gattc_if;
m_semaphoreRegEvt.give();
// pass on the registration status result, in case of failure
m_semaphoreRegEvt.give(evtParam->reg.status);
break;
} // ESP_GATTC_REG_EVT
@ -520,6 +546,39 @@ uint16_t BLEClient::getMTU() {
return m_mtu;
}
/**
@brief Set the local and remote MTU size.
Should be called once after client connects if MTU size needs to be changed.
@return bool indicating if MTU was successfully set locally and on remote.
*/
bool BLEClient::setMTU(uint16_t mtu)
{
esp_err_t err = esp_ble_gatt_set_local_mtu(mtu); //First must set local MTU value.
if (err == ESP_OK)
{
err = esp_ble_gattc_send_mtu_req(m_gattc_if,m_conn_id); //Once local is set successfully set remote size
if (err!=ESP_OK)
{
log_e("Error setting send MTU request MTU: %d err=%d", mtu,err);
return false;
}
}
else
{
log_e("can't set local mtu value: %d", mtu);
return false;
}
log_v("<< setLocalMTU");
m_mtu = mtu; //successfully changed
return true;
}
/**
* @brief Return a string representation of this client.
* @return A string representation of this client.

View File

@ -57,7 +57,8 @@ public:
uint16_t getConnId();
esp_gatt_if_t getGattcIf();
uint16_t getMTU();
bool setMTU(uint16_t mtu);
uint16_t m_appId;
private:
friend class BLEDevice;

View File

@ -52,6 +52,7 @@ BLERemoteCharacteristic::BLERemoteCharacteristic(
*/
BLERemoteCharacteristic::~BLERemoteCharacteristic() {
removeDescriptors(); // Release resources for any descriptor information we may have allocated.
free(m_rawData);
} // ~BLERemoteCharacteristic
@ -245,6 +246,10 @@ void BLERemoteCharacteristic::gattClientEventHandler(esp_gattc_cb_event_t event,
}
break;
case ESP_GATTC_DISCONNECT_EVT:
m_semaphoreWriteCharEvt.give(1);
break;
default:
break;
} // End switch
@ -453,7 +458,7 @@ std::string BLERemoteCharacteristic::readValue() {
* unregistering a notification.
* @return N/A.
*/
void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback, bool notifications) {
void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback, bool notifications, bool descriptorRequiresRegistration) {
log_v(">> registerForNotify(): %s", toString().c_str());
m_notifyCallback = notifyCallback; // Save the notification callback.
@ -474,7 +479,7 @@ void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback,
uint8_t val[] = {0x01, 0x00};
if(!notifications) val[0] = 0x02;
BLERemoteDescriptor* desc = getDescriptor(BLEUUID((uint16_t)0x2902));
if (desc != nullptr)
if (desc != nullptr && descriptorRequiresRegistration)
desc->writeValue(val, 2, true);
} // End Register
else { // If we weren't passed a callback function, then this is an unregistration.
@ -490,7 +495,7 @@ void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback,
uint8_t val[] = {0x00, 0x00};
BLERemoteDescriptor* desc = getDescriptor((uint16_t)0x2902);
if (desc != nullptr)
if (desc != nullptr && descriptorRequiresRegistration)
desc->writeValue(val, 2, true);
} // End Unregister

View File

@ -11,6 +11,7 @@
#if defined(CONFIG_BLUEDROID_ENABLED)
#include <string>
#include <functional>
#include <esp_gattc_api.h>
@ -21,8 +22,7 @@
class BLERemoteService;
class BLERemoteDescriptor;
typedef void (*notify_callback)(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify);
typedef std::function<void(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify)> notify_callback;
/**
* @brief A model of a remote %BLE characteristic.
*/
@ -39,6 +39,7 @@ public:
bool canWriteNoResponse();
BLERemoteDescriptor* getDescriptor(BLEUUID uuid);
std::map<std::string, BLERemoteDescriptor*>* getDescriptors();
BLERemoteService* getRemoteService();
uint16_t getHandle();
BLEUUID getUUID();
std::string readValue();
@ -46,7 +47,7 @@ public:
uint16_t readUInt16();
uint32_t readUInt32();
float readFloat();
void registerForNotify(notify_callback _callback, bool notifications = true);
void registerForNotify(notify_callback _callback, bool notifications = true, bool descriptorRequiresRegistration = true);
void writeValue(uint8_t* data, size_t length, bool response = false);
void writeValue(std::string newValue, bool response = false);
void writeValue(uint8_t newValue, bool response = false);
@ -63,7 +64,6 @@ private:
// Private member functions
void gattClientEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* evtParam);
BLERemoteService* getRemoteService();
void removeDescriptors();
void retrieveDescriptors();

View File

@ -245,6 +245,7 @@ std::map<uint16_t, BLERemoteCharacteristic*>* BLERemoteService::getCharacteristi
*/
void BLERemoteService::getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>** pCharacteristicMap) {
log_v(">> getCharacteristics() for service: %s", getUUID().toString().c_str());
(void)pCharacteristicMap;
// If is possible that we have not read the characteristics associated with the service so do that
// now. The request to retrieve the characteristics by calling "retrieveCharacteristics" is a blocking
// call and does not return until all the characteristics are available.

View File

@ -0,0 +1,75 @@
//This example code is in the Public Domain (or CC0 licensed, at your option.)
//By Richard Li - 2020
//
//This example creates a bridge between Serial and Classical Bluetooth (SPP with authentication)
//and also demonstrate that SerialBT have the same functionalities of a normal Serial
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
boolean confirmRequestPending = true;
void BTConfirmRequestCallback(uint32_t numVal)
{
confirmRequestPending = true;
Serial.println(numVal);
}
void BTAuthCompleteCallback(boolean success)
{
confirmRequestPending = false;
if (success)
{
Serial.println("Pairing success!!");
}
else
{
Serial.println("Pairing failed, rejected by user!!");
}
}
void setup()
{
Serial.begin(115200);
SerialBT.enableSSP();
SerialBT.onConfirmRequest(BTConfirmRequestCallback);
SerialBT.onAuthComplete(BTAuthCompleteCallback);
SerialBT.begin("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
}
void loop()
{
if (confirmRequestPending)
{
if (Serial.available())
{
int dat = Serial.read();
if (dat == 'Y' || dat == 'y')
{
SerialBT.confirmReply(true);
}
else
{
SerialBT.confirmReply(false);
}
}
}
else
{
if (Serial.available())
{
SerialBT.write(Serial.read());
}
if (SerialBT.available())
{
Serial.write(SerialBT.read());
}
delay(20);
}
}

View File

@ -0,0 +1,52 @@
#include <BluetoothSerial.h>
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
#define BT_DISCOVER_TIME 10000
static bool btScanAsync = true;
static bool btScanSync = true;
void btAdvertisedDeviceFound(BTAdvertisedDevice* pDevice) {
Serial.printf("Found a device asynchronously: %s\n", pDevice->toString().c_str());
}
void setup() {
Serial.begin(115200);
SerialBT.begin("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
if (btScanAsync) {
Serial.print("Starting discoverAsync...");
if (SerialBT.discoverAsync(btAdvertisedDeviceFound)) {
Serial.println("Findings will be reported in \"btAdvertisedDeviceFound\"");
delay(10000);
Serial.print("Stopping discoverAsync... ");
SerialBT.discoverAsyncStop();
Serial.println("stopped");
} else {
Serial.println("Error on discoverAsync f.e. not workin after a \"connect\"");
}
}
if (btScanSync) {
Serial.println("Starting discover...");
BTScanResults *pResults = SerialBT.discover(BT_DISCOVER_TIME);
if (pResults)
pResults->dump(&Serial);
else
Serial.println("Error on BT Scan, no result!");
}
}
void loop() {
delay(100);
}

View File

@ -0,0 +1,96 @@
/*
* BTAddress.cpp
*
* Created on: Jul 2, 2017
* Author: kolban
* Ported on: Feb 5, 2021
* Author: Thomas M. (ArcticSnowSky)
*/
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "BTAddress.h"
#include <string>
#include <sstream>
#include <iomanip>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#endif
/**
* @brief Create an address from the native ESP32 representation.
* @param [in] address The native representation.
*/
BTAddress::BTAddress(esp_bd_addr_t address) {
memcpy(m_address, address, ESP_BD_ADDR_LEN);
} // BTAddress
/**
* @brief Create an address from a hex string
*
* A hex string is of the format:
* ```
* 00:00:00:00:00:00
* ```
* which is 17 characters in length.
*
* @param [in] stringAddress The hex representation of the address.
*/
BTAddress::BTAddress(std::string stringAddress) {
if (stringAddress.length() != 17) return;
int data[6];
sscanf(stringAddress.c_str(), "%x:%x:%x:%x:%x:%x", &data[0], &data[1], &data[2], &data[3], &data[4], &data[5]);
m_address[0] = (uint8_t) data[0];
m_address[1] = (uint8_t) data[1];
m_address[2] = (uint8_t) data[2];
m_address[3] = (uint8_t) data[3];
m_address[4] = (uint8_t) data[4];
m_address[5] = (uint8_t) data[5];
} // BTAddress
/**
* @brief Determine if this address equals another.
* @param [in] otherAddress The other address to compare against.
* @return True if the addresses are equal.
*/
bool BTAddress::equals(BTAddress otherAddress) {
return memcmp(otherAddress.getNative(), m_address, 6) == 0;
} // equals
/**
* @brief Return the native representation of the address.
* @return The native representation of the address.
*/
esp_bd_addr_t *BTAddress::getNative() {
return &m_address;
} // getNative
/**
* @brief Convert a BT address to a string.
*
* A string representation of an address is in the format:
*
* ```
* xx:xx:xx:xx:xx:xx
* ```
*
* @return The string representation of the address.
*/
std::string BTAddress::toString() {
auto size = 18;
char *res = (char*)malloc(size);
snprintf(res, size, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[0], m_address[1], m_address[2], m_address[3], m_address[4], m_address[5]);
std::string ret(res);
free(res);
return ret;
} // toString
#endif

View File

@ -0,0 +1,36 @@
/*
* BTAddress.h
*
* Created on: Jul 2, 2017
* Author: kolban
* Ported on: Feb 5, 2021
* Author: Thomas M. (ArcticSnowSky)
*/
#ifndef COMPONENTS_CPP_UTILS_BTADDRESS_H_
#define COMPONENTS_CPP_UTILS_BTADDRESS_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <esp_gap_bt_api.h> // ESP32 BT
#include <string>
/**
* @brief A %BT device address.
*
* Every %BT device has a unique address which can be used to identify it and form connections.
*/
class BTAddress {
public:
BTAddress(esp_bd_addr_t address);
BTAddress(std::string stringAddress);
bool equals(BTAddress otherAddress);
esp_bd_addr_t* getNative();
std::string toString();
private:
esp_bd_addr_t m_address;
};
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BTADDRESS_H_ */

View File

@ -0,0 +1,65 @@
/*
* BTAdvertisedDevice.h
*
* Created on: Feb 5, 2021
* Author: Thomas M. (ArcticSnowSky)
*/
#ifndef __BTADVERTISEDDEVICE_H__
#define __BTADVERTISEDDEVICE_H__
#include "BTAddress.h"
class BTAdvertisedDevice {
public:
virtual ~BTAdvertisedDevice() = default;
virtual BTAddress getAddress();
virtual uint32_t getCOD();
virtual std::string getName();
virtual int8_t getRSSI();
virtual bool haveCOD();
virtual bool haveName();
virtual bool haveRSSI();
virtual std::string toString();
};
class BTAdvertisedDeviceSet : public virtual BTAdvertisedDevice {
public:
BTAdvertisedDeviceSet();
//~BTAdvertisedDeviceSet() = default;
BTAddress getAddress();
uint32_t getCOD();
std::string getName();
int8_t getRSSI();
bool haveCOD();
bool haveName();
bool haveRSSI();
std::string toString();
void setAddress(BTAddress address);
void setCOD(uint32_t cod);
void setName(std::string name);
void setRSSI(int8_t rssi);
bool m_haveCOD;
bool m_haveName;
bool m_haveRSSI;
BTAddress m_address = BTAddress((uint8_t*)"\0\0\0\0\0\0");
uint32_t m_cod;
std::string m_name;
int8_t m_rssi;
};
#endif

View File

@ -0,0 +1,78 @@
/*
* BTAdvertisedDeviceSet.cpp
*
* Created on: Feb 5, 2021
* Author: Thomas M. (ArcticSnowSky)
*/
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
//#include <map>
#include "BTAdvertisedDevice.h"
//#include "BTScan.h"
BTAdvertisedDeviceSet::BTAdvertisedDeviceSet() {
m_cod = 0;
m_name = "";
m_rssi = 0;
m_haveCOD = false;
m_haveName = false;
m_haveRSSI = false;
} // BTAdvertisedDeviceSet
BTAddress BTAdvertisedDeviceSet::getAddress() { return m_address; }
uint32_t BTAdvertisedDeviceSet::getCOD() { return m_cod; }
std::string BTAdvertisedDeviceSet::getName() { return m_name; }
int8_t BTAdvertisedDeviceSet::getRSSI() { return m_rssi; }
bool BTAdvertisedDeviceSet::haveCOD() { return m_haveCOD; }
bool BTAdvertisedDeviceSet::haveName() { return m_haveName; }
bool BTAdvertisedDeviceSet::haveRSSI() { return m_haveRSSI; }
/**
* @brief Create a string representation of this device.
* @return A string representation of this device.
*/
std::string BTAdvertisedDeviceSet::toString() {
std::string res = "Name: " + getName() + ", Address: " + getAddress().toString();
if (haveCOD()) {
char val[6];
snprintf(val, sizeof(val), "%d", getCOD());
res += ", cod: ";
res += val;
}
if (haveRSSI()) {
char val[6];
snprintf(val, sizeof(val), "%d", (int8_t)getRSSI());
res += ", rssi: ";
res += val;
}
return res;
} // toString
void BTAdvertisedDeviceSet::setAddress(BTAddress address) {
m_address = address;
}
void BTAdvertisedDeviceSet::setCOD(uint32_t cod) {
m_cod = cod;
m_haveCOD = true;
}
void BTAdvertisedDeviceSet::setName(std::string name) {
m_name = name;
m_haveName = true;
}
void BTAdvertisedDeviceSet::setRSSI(int8_t rssi) {
m_rssi = rssi;
m_haveRSSI = true;
}
#endif /* CONFIG_BT_ENABLED */

View File

@ -0,0 +1,42 @@
/*
* BTScan.h
*
* Created on: Feb 5, 2021
* Author: Thomas M. (ArcticSnowSky)
*/
#ifndef __BTSCAN_H__
#define __BTSCAN_H__
#include <map>
#include <string>
#include <Print.h>
#include "BTAddress.h"
#include "BTAdvertisedDevice.h"
class BTAdvertisedDevice;
class BTAdvertisedDeviceSet;
class BTScanResults {
public:
virtual ~BTScanResults() = default;
virtual void dump(Print *print = nullptr);
virtual int getCount();
virtual BTAdvertisedDevice* getDevice(uint32_t i);
};
class BTScanResultsSet : public BTScanResults {
public:
void dump(Print *print = nullptr);
int getCount();
BTAdvertisedDevice* getDevice(uint32_t i);
bool add(BTAdvertisedDeviceSet advertisedDevice, bool unique = true);
void clear();
std::map<std::string, BTAdvertisedDeviceSet> m_vectorAdvertisedDevices;
};
#endif

View File

@ -0,0 +1,95 @@
/*
* BTScanResultsSet.cpp
*
* Created on: Feb 5, 2021
* Author: Thomas M. (ArcticSnowSky)
*/
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <esp_err.h>
#include "BTAdvertisedDevice.h"
#include "BTScan.h"
//#include "GeneralUtils.h"
#include "esp32-hal-log.h"
class BTAdvertisedDevice;
/**
* @brief Dump the scan results to the log.
*/
void BTScanResultsSet::dump(Print *print) {
int cnt = getCount();
if (print == nullptr) {
log_v(">> Dump scan results : %d", cnt);
for (int i=0; i < cnt; i++) {
BTAdvertisedDevice* dev = getDevice(i);
if (dev)
log_d("- %d: %s\n", i+1, dev->toString().c_str());
else
log_d("- %d is null\n", i+1);
}
log_v("-- dump finished --");
} else {
print->printf(">> Dump scan results: %d\n", cnt);
for (int i=0; i < cnt; i++) {
BTAdvertisedDevice* dev = getDevice(i);
if (dev)
print->printf("- %d: %s\n", i+1, dev->toString().c_str());
else
print->printf("- %d is null\n", i+1);
}
print->println("-- Dump finished --");
}
} // dump
/**
* @brief Return the count of devices found in the last scan.
* @return The number of devices found in the last scan.
*/
int BTScanResultsSet::getCount() {
return m_vectorAdvertisedDevices.size();
} // getCount
/**
* @brief Return the specified device at the given index.
* The index should be between 0 and getCount()-1.
* @param [in] i The index of the device.
* @return The device at the specified index.
*/
BTAdvertisedDevice* BTScanResultsSet::getDevice(uint32_t i) {
if (i < 0)
return nullptr;
uint32_t x = 0;
BTAdvertisedDeviceSet* pDev = &m_vectorAdvertisedDevices.begin()->second;
for (auto it = m_vectorAdvertisedDevices.begin(); it != m_vectorAdvertisedDevices.end(); it++) {
pDev = &it->second;
if (x==i) break;
x++;
}
return x==i ? pDev : nullptr;
}
void BTScanResultsSet::clear() {
//for(auto _dev : m_vectorAdvertisedDevices)
// delete _dev.second;
m_vectorAdvertisedDevices.clear();
}
bool BTScanResultsSet::add(BTAdvertisedDeviceSet advertisedDevice, bool unique) {
std::string key = advertisedDevice.getAddress().toString();
if (!unique || m_vectorAdvertisedDevices.count(key) == 0) {
m_vectorAdvertisedDevices.insert(std::pair<std::string, BTAdvertisedDeviceSet>(key, advertisedDevice));
return true;
} else
return false;
}
#endif

256
libraries/BluetoothSerial/src/BluetoothSerial.cpp Executable file → Normal file
View File

@ -42,15 +42,23 @@ const char * _spp_server_name = "ESP32SPP";
#define RX_QUEUE_SIZE 512
#define TX_QUEUE_SIZE 32
#define SPP_TX_QUEUE_TIMEOUT 1000
#define SPP_TX_DONE_TIMEOUT 1000
#define SPP_CONGESTED_TIMEOUT 1000
static uint32_t _spp_client = 0;
static xQueueHandle _spp_rx_queue = NULL;
static xQueueHandle _spp_tx_queue = NULL;
static SemaphoreHandle_t _spp_tx_done = NULL;
static TaskHandle_t _spp_task_handle = NULL;
static EventGroupHandle_t _spp_event_group = NULL;
static EventGroupHandle_t _bt_event_group = NULL;
static boolean secondConnectionAttempt;
static esp_spp_cb_t * custom_spp_callback = NULL;
static BluetoothSerialDataCb custom_data_callback = NULL;
static esp_bd_addr_t current_bd_addr;
static ConfirmRequestCb confirm_request_callback = NULL;
static AuthCompleteCb auth_complete_callback = NULL;
#define INQ_LEN 0x10
#define INQ_NUM_RSPS 20
@ -65,11 +73,18 @@ static int _pin_len;
static bool _isPinSet;
static bool _enableSSP;
static BTScanResultsSet scanResults;
static BTAdvertisedDeviceCb advertisedDeviceCb = nullptr;
#define SPP_RUNNING 0x01
#define SPP_CONNECTED 0x02
#define SPP_CONGESTED 0x04
#define SPP_DISCONNECTED 0x08
#define BT_DISCOVERY_RUNNING 0x01
#define BT_DISCOVERY_COMPLETED 0x02
typedef struct {
size_t len;
uint8_t data[];
@ -140,7 +155,7 @@ static esp_err_t _spp_queue_packet(uint8_t *data, size_t len){
}
packet->len = len;
memcpy(packet->data, data, len);
if (xQueueSend(_spp_tx_queue, &packet, portMAX_DELAY) != pdPASS) {
if (!_spp_tx_queue || xQueueSend(_spp_tx_queue, &packet, SPP_TX_QUEUE_TIMEOUT) != pdPASS) {
log_e("SPP TX Queue Send Failed!");
free(packet);
return ESP_FAIL;
@ -153,19 +168,25 @@ static uint8_t _spp_tx_buffer[SPP_TX_MAX];
static uint16_t _spp_tx_buffer_len = 0;
static bool _spp_send_buffer(){
if((xEventGroupWaitBits(_spp_event_group, SPP_CONGESTED, pdFALSE, pdTRUE, portMAX_DELAY) & SPP_CONGESTED) != 0){
if((xEventGroupWaitBits(_spp_event_group, SPP_CONGESTED, pdFALSE, pdTRUE, SPP_CONGESTED_TIMEOUT) & SPP_CONGESTED) != 0){
if(!_spp_client){
log_v("SPP Client Gone!");
return false;
}
log_v("SPP Write %u", _spp_tx_buffer_len);
esp_err_t err = esp_spp_write(_spp_client, _spp_tx_buffer_len, _spp_tx_buffer);
if(err != ESP_OK){
log_e("SPP Write Failed! [0x%X]", err);
return false;
}
_spp_tx_buffer_len = 0;
if(xSemaphoreTake(_spp_tx_done, portMAX_DELAY) != pdTRUE){
if(xSemaphoreTake(_spp_tx_done, SPP_TX_DONE_TIMEOUT) != pdTRUE){
log_e("SPP Ack Failed!");
return false;
}
return true;
}
log_e("SPP Write Congested!");
return false;
}
@ -191,13 +212,18 @@ static void _spp_tx_task(void * arg){
_spp_tx_buffer_len = SPP_TX_MAX;
data += to_send;
len -= to_send;
_spp_send_buffer();
if(!_spp_send_buffer()){
len = 0;
}
while(len >= SPP_TX_MAX){
memcpy(_spp_tx_buffer, data, SPP_TX_MAX);
_spp_tx_buffer_len = SPP_TX_MAX;
data += SPP_TX_MAX;
len -= SPP_TX_MAX;
_spp_send_buffer();
if(!_spp_send_buffer()){
len = 0;
break;
}
}
if(len){
memcpy(_spp_tx_buffer, data, len);
@ -236,26 +262,36 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
break;
case ESP_SPP_SRV_OPEN_EVT://Server connection open
log_i("ESP_SPP_SRV_OPEN_EVT");
if (!_spp_client){
_spp_client = param->open.handle;
if (param->srv_open.status == ESP_SPP_SUCCESS) {
log_i("ESP_SPP_SRV_OPEN_EVT: %u", _spp_client);
if (!_spp_client){
_spp_client = param->srv_open.handle;
_spp_tx_buffer_len = 0;
} else {
secondConnectionAttempt = true;
esp_spp_disconnect(param->srv_open.handle);
}
xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
} else {
secondConnectionAttempt = true;
esp_spp_disconnect(param->open.handle);
log_e("ESP_SPP_SRV_OPEN_EVT Failed!, status:%d", param->srv_open.status);
}
xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
break;
case ESP_SPP_CLOSE_EVT://Client connection closed
log_i("ESP_SPP_CLOSE_EVT");
if(secondConnectionAttempt) {
secondConnectionAttempt = false;
if ((param->close.async == false && param->close.status == ESP_SPP_SUCCESS) || param->close.async) {
log_i("ESP_SPP_CLOSE_EVT: %u", secondConnectionAttempt);
if(secondConnectionAttempt) {
secondConnectionAttempt = false;
} else {
_spp_client = 0;
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
}
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
} else {
_spp_client = 0;
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
}
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
log_e("ESP_SPP_CLOSE_EVT failed!, status:%d", param->close.status);
}
break;
case ESP_SPP_CONG_EVT://connection congestion status changed
@ -268,11 +304,15 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
break;
case ESP_SPP_WRITE_EVT://write operation completed
if(param->write.cong){
xEventGroupClearBits(_spp_event_group, SPP_CONGESTED);
if (param->write.status == ESP_SPP_SUCCESS) {
if(param->write.cong){
xEventGroupClearBits(_spp_event_group, SPP_CONGESTED);
}
log_v("ESP_SPP_WRITE_EVT: %u %s", param->write.len, param->write.cong?"CONGESTED":"");
} else {
log_e("ESP_SPP_WRITE_EVT failed!, status:%d", param->write.status);
}
xSemaphoreGive(_spp_tx_done);//we can try to send another packet
log_v("ESP_SPP_WRITE_EVT: %u %s", param->write.len, param->write.cong?"CONGESTED":"FREE");
break;
case ESP_SPP_DATA_IND_EVT://connection received data
@ -297,6 +337,8 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
if (param->disc_comp.status == ESP_SPP_SUCCESS) {
log_i("ESP_SPP_DISCOVERY_COMP_EVT: spp connect to remote");
esp_spp_connect(ESP_SPP_SEC_AUTHENTICATE, ESP_SPP_ROLE_MASTER, param->disc_comp.scn[0], _peer_bd_addr);
} else {
log_e("ESP_SPP_DISCOVERY_COMP_EVT failed!, status:%d", param->disc_comp.status);
}
break;
@ -310,6 +352,7 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
}
xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
break;
case ESP_SPP_START_EVT://server started
@ -333,15 +376,16 @@ void BluetoothSerial::onData(BluetoothSerialDataCb cb){
static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
{
switch(event){
case ESP_BT_GAP_DISC_RES_EVT:
case ESP_BT_GAP_DISC_RES_EVT: {
log_i("ESP_BT_GAP_DISC_RES_EVT");
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)
char bda_str[18];
log_i("Scanned device: %s", bda2str(param->disc_res.bda, bda_str, 18));
#endif
BTAdvertisedDeviceSet advertisedDevice;
uint8_t peer_bdname_len = 0;
char peer_bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
for (int i = 0; i < param->disc_res.num_prop; i++) {
uint8_t peer_bdname_len;
char peer_bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
switch(param->disc_res.prop[i].type) {
case ESP_BT_GAP_DEV_PROP_EIR:
if (get_name_from_eir((uint8_t*)param->disc_res.prop[i].val, peer_bdname, &peer_bdname_len)) {
@ -374,10 +418,24 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
case ESP_BT_GAP_DEV_PROP_COD:
log_d("ESP_BT_GAP_DEV_PROP_COD");
if (param->disc_res.prop[i].len <= sizeof(int)) {
uint32_t cod = 0;
memcpy(&cod, param->disc_res.prop[i].val, param->disc_res.prop[i].len);
advertisedDevice.setCOD(cod);
} else {
log_d("Value size larger than integer");
}
break;
case ESP_BT_GAP_DEV_PROP_RSSI:
log_d("ESP_BT_GAP_DEV_PROP_RSSI");
if (param->disc_res.prop[i].len <= sizeof(int)) {
uint8_t rssi = 0;
memcpy(&rssi, param->disc_res.prop[i].val, param->disc_res.prop[i].len);
advertisedDevice.setRSSI(rssi);
} else {
log_d("Value size larger than integer");
}
break;
default:
@ -386,24 +444,46 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
if (_isRemoteAddressSet)
break;
}
break;
if (peer_bdname_len)
advertisedDevice.setName(peer_bdname);
esp_bd_addr_t addr;
memcpy(addr, param->disc_res.bda, ESP_BD_ADDR_LEN);
advertisedDevice.setAddress(BTAddress(addr));
if (scanResults.add(advertisedDevice) && advertisedDeviceCb)
advertisedDeviceCb(&advertisedDevice);
}
break;
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT:
log_i("ESP_BT_GAP_DISC_STATE_CHANGED_EVT");
if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) {
xEventGroupClearBits(_bt_event_group, BT_DISCOVERY_RUNNING);
xEventGroupSetBits(_bt_event_group, BT_DISCOVERY_COMPLETED);
} else { // ESP_BT_GAP_DISCOVERY_STARTED
xEventGroupClearBits(_bt_event_group, BT_DISCOVERY_COMPLETED);
xEventGroupSetBits(_bt_event_group, BT_DISCOVERY_RUNNING);
}
break;
case ESP_BT_GAP_RMT_SRVCS_EVT:
log_i( "ESP_BT_GAP_RMT_SRVCS_EVT");
log_i( "ESP_BT_GAP_RMT_SRVCS_EVT: status = %d, num_uuids = %d", param->rmt_srvcs.stat, param->rmt_srvcs.num_uuids);
break;
case ESP_BT_GAP_RMT_SRVC_REC_EVT:
log_i("ESP_BT_GAP_RMT_SRVC_REC_EVT");
log_i("ESP_BT_GAP_RMT_SRVC_REC_EVT: status = %d", param->rmt_srvc_rec.stat);
break;
case ESP_BT_GAP_AUTH_CMPL_EVT:
if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) {
log_v("authentication success: %s", param->auth_cmpl.device_name);
if (auth_complete_callback) {
auth_complete_callback(true);
}
} else {
log_e("authentication failed, status:%d", param->auth_cmpl.stat);
if (auth_complete_callback) {
auth_complete_callback(false);
}
}
break;
@ -425,7 +505,13 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
case ESP_BT_GAP_CFM_REQ_EVT:
log_i("ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val);
esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true);
if (confirm_request_callback) {
memcpy(current_bd_addr, param->cfm_req.bda, sizeof(esp_bd_addr_t));
confirm_request_callback(param->cfm_req.num_val);
}
else {
esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true);
}
break;
case ESP_BT_GAP_KEY_NOTIF_EVT:
@ -443,6 +529,14 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
static bool _init_bt(const char *deviceName)
{
if(!_bt_event_group){
_bt_event_group = xEventGroupCreate();
if(!_bt_event_group){
log_e("BT Event Group Create Failed!");
return false;
}
xEventGroupClearBits(_bt_event_group, 0xFFFFFF);
}
if(!_spp_event_group){
_spp_event_group = xEventGroupCreate();
if(!_spp_event_group){
@ -504,7 +598,9 @@ static bool _init_bt(const char *deviceName)
}
}
if (_isMaster && esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) {
// Why only master need this? Slave need this during pairing as well
// if (_isMaster && esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) {
if (esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) {
log_e("gap register failed");
return false;
}
@ -519,9 +615,9 @@ static bool _init_bt(const char *deviceName)
return false;
}
if (esp_bt_sleep_disable() != ESP_OK){
log_e("esp_bt_sleep_disable failed");
}
// if (esp_bt_sleep_disable() != ESP_OK){
// log_e("esp_bt_sleep_disable failed");
// }
log_i("device name set");
esp_bt_dev_set_device_name(deviceName);
@ -585,6 +681,10 @@ static bool _stop_bt()
vSemaphoreDelete(_spp_tx_done);
_spp_tx_done = NULL;
}
if (_bt_event_group) {
vEventGroupDelete(_bt_event_group);
_bt_event_group = NULL;
}
return true;
}
@ -593,6 +693,11 @@ static bool waitForConnect(int timeout) {
return (xEventGroupWaitBits(_spp_event_group, SPP_CONNECTED, pdFALSE, pdTRUE, xTicksToWait) & SPP_CONNECTED) != 0;
}
static bool waitForDiscovered(int timeout) {
TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
return (xEventGroupWaitBits(_spp_event_group, BT_DISCOVERY_COMPLETED, pdFALSE, pdTRUE, xTicksToWait) & BT_DISCOVERY_COMPLETED) != 0;
}
/*
* Serial Bluetooth Arduino
*
@ -666,7 +771,7 @@ void BluetoothSerial::flush()
{
if (_spp_tx_queue != NULL){
while(uxQueueMessagesWaiting(_spp_tx_queue) > 0){
delay(5);
delay(100);
}
}
}
@ -676,6 +781,22 @@ void BluetoothSerial::end()
_stop_bt();
}
void BluetoothSerial::onConfirmRequest(ConfirmRequestCb cb)
{
confirm_request_callback = cb;
}
void BluetoothSerial::onAuthComplete(AuthCompleteCb cb)
{
auth_complete_callback = cb;
}
void BluetoothSerial::confirmReply(boolean confirm)
{
esp_bt_gap_ssp_confirm_reply(current_bd_addr, confirm);
}
esp_err_t BluetoothSerial::register_callback(esp_spp_cb_t * callback)
{
custom_spp_callback = callback;
@ -816,6 +937,73 @@ bool BluetoothSerial::isReady(bool checkMaster, int timeout) {
return (xEventGroupWaitBits(_spp_event_group, SPP_RUNNING, pdFALSE, pdTRUE, xTicksToWait) & SPP_RUNNING) != 0;
}
/**
* @brief RemoteName or address are not allowed to be set during discovery
* (otherwhise it might connect automatically and stop discovery)
* @param[in] timeoutMs can range from MIN_INQ_TIME to MAX_INQ_TIME
* @return in case of Error immediately Empty ScanResults.
*/
BTScanResults* BluetoothSerial::discover(int timeoutMs) {
scanResults.clear();
if (timeoutMs < MIN_INQ_TIME || timeoutMs > MAX_INQ_TIME || strlen(_remote_name) || _isRemoteAddressSet)
return nullptr;
int timeout = timeoutMs / INQ_TIME;
log_i("discover::disconnect");
disconnect();
log_i("discovering");
// will resolve name to address first - it may take a while
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
if (esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, timeout, 0) == ESP_OK) {
waitForDiscovered(timeoutMs);
esp_bt_gap_cancel_discovery();
}
return &scanResults;
}
/**
* @brief RemoteName or address are not allowed to be set during discovery
* (otherwhise it might connect automatically and stop discovery)
* @param[in] cb called when a [b]new[/b] device has been discovered
* @param[in] timeoutMs can be 0 or range from MIN_INQ_TIME to MAX_INQ_TIME
*
* @return Wheter start was successfull or problems with params
*/
bool BluetoothSerial::discoverAsync(BTAdvertisedDeviceCb cb, int timeoutMs) {
scanResults.clear();
if (strlen(_remote_name) || _isRemoteAddressSet)
return false;
int timeout = timeoutMs / INQ_TIME;
disconnect();
advertisedDeviceCb = cb;
log_i("discovering");
// will resolve name to address first - it may take a while
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
if (timeout > 0)
return esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, timeout, 0) == ESP_OK;
else return esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, ESP_BT_GAP_MAX_INQ_LEN, 0) == ESP_OK;
}
/** @brief Stops the asynchronous discovery and clears the callback */
void BluetoothSerial::discoverAsyncStop() {
esp_bt_gap_cancel_discovery();
advertisedDeviceCb = nullptr;
}
/** @brief Clears scanresult entries */
void BluetoothSerial::discoverClear() {
scanResults.clear();
}
/** @brief Can be used while discovering asynchronously
* Will be returned also on synchronous discovery.
*
* @return BTScanResults contains several information of found devices
*/
BTScanResults* BluetoothSerial::getScanResults() {
return &scanResults;
}
BluetoothSerial::operator bool() const
{
return true;

19
libraries/BluetoothSerial/src/BluetoothSerial.h Executable file → Normal file
View File

@ -21,10 +21,15 @@
#include "Arduino.h"
#include "Stream.h"
#include <esp_gap_bt_api.h>
#include <esp_spp_api.h>
#include <functional>
#include "BTScan.h"
typedef std::function<void(const uint8_t *buffer, size_t size)> BluetoothSerialDataCb;
typedef std::function<void(uint32_t num_val)> ConfirmRequestCb;
typedef std::function<void(boolean success)> AuthCompleteCb;
typedef std::function<void(BTAdvertisedDevice* pAdvertisedDevice)> BTAdvertisedDeviceCb;
class BluetoothSerial: public Stream
{
@ -47,6 +52,10 @@ class BluetoothSerial: public Stream
void end(void);
void onData(BluetoothSerialDataCb cb);
esp_err_t register_callback(esp_spp_cb_t * callback);
void onConfirmRequest(ConfirmRequestCb cb);
void onAuthComplete(AuthCompleteCb cb);
void confirmReply(boolean confirm);
void enableSSP();
bool setPin(const char *pin);
@ -57,6 +66,16 @@ class BluetoothSerial: public Stream
bool isReady(bool checkMaster=false, int timeout=0);
bool disconnect();
bool unpairDevice(uint8_t remoteAddress[]);
BTScanResults* discover(int timeout=0x30*1280);
bool discoverAsync(BTAdvertisedDeviceCb cb, int timeout=0x30*1280);
void discoverAsyncStop();
void discoverClear();
BTScanResults* getScanResults();
const int INQ_TIME = 1280; // Inquire Time unit 1280 ms
const int MIN_INQ_TIME = (ESP_BT_GAP_MIN_INQ_LEN * INQ_TIME);
const int MAX_INQ_TIME = (ESP_BT_GAP_MAX_INQ_LEN * INQ_TIME);
operator bool() const;
private:

View File

@ -382,6 +382,9 @@ size_t EEPROMClass::readString (int address, char* value, size_t maxLen)
if (address + len > _size)
return 0;
if (len > maxLen)
return 0; //Maybe return part of the string instead?
memcpy((uint8_t*) value, _data + address, len);
value[len] = 0;
return len;
@ -400,7 +403,7 @@ String EEPROMClass::readString (int address)
if (address + len > _size)
return String();
char value[len];
char value[len+1];
memcpy((uint8_t*) value, _data + address, len);
value[len] = 0;
return String(value);

View File

@ -9,9 +9,9 @@
*/
// Set up the rgb led names
uint8_t ledR = A4;
uint8_t ledG = A5;
uint8_t ledB = A18;
uint8_t ledR = 2;
uint8_t ledG = 4;
uint8_t ledB = 5;
uint8_t ledArray[3] = {1, 2, 3}; // three led channels

Some files were not shown because too many files have changed in this diff Show More