Merge branch 'development' into prerelease-14.4.0
This commit is contained in:
commit
f62080bc54
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -7,7 +7,7 @@
|
|||||||
- [ ] Only relevant files were touched
|
- [ ] Only relevant files were touched
|
||||||
- [ ] Only one feature/fix was added per PR and the code change compiles without warnings
|
- [ ] Only one feature/fix was added per PR and the code change compiles without warnings
|
||||||
- [ ] The code change is tested and works with Tasmota core ESP8266 V.2.7.8
|
- [ ] The code change is tested and works with Tasmota core ESP8266 V.2.7.8
|
||||||
- [ ] The code change is tested and works with Tasmota core ESP32 V.3.1.0.240926
|
- [ ] The code change is tested and works with Tasmota core ESP32 V.3.1.0.241206
|
||||||
- [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla).
|
- [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla).
|
||||||
|
|
||||||
_NOTE: The code change must pass CI tests. **Your PR cannot be merged unless tests pass**_
|
_NOTE: The code change must pass CI tests. **Your PR cannot be merged unless tests pass**_
|
||||||
|
|||||||
4
.github/workflows/build_all_the_things.yml
vendored
4
.github/workflows/build_all_the_things.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
|||||||
fail-fast: true
|
fail-fast: true
|
||||||
matrix:
|
matrix:
|
||||||
variant:
|
variant:
|
||||||
- tasmota32solo1-safeboot
|
- tasmota32-webcam
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
@ -53,7 +53,7 @@ jobs:
|
|||||||
fail-fast: true
|
fail-fast: true
|
||||||
matrix:
|
matrix:
|
||||||
variant:
|
variant:
|
||||||
- tasmota32-webcam
|
- tasmota32solo1-safeboot
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
|
|||||||
@ -283,7 +283,7 @@ Note: the `minimal` variant is not listed as it shouldn't be used outside of the
|
|||||||
| USE_SONOFF_SPM | | / x | | | | |
|
| USE_SONOFF_SPM | | / x | | | | |
|
||||||
| USE_DISPLAY_TM1621_SONOFF | | / x | | | | |
|
| USE_DISPLAY_TM1621_SONOFF | | / x | | | | |
|
||||||
| USE_SHELLY_PRO | | / x | | | | |
|
| USE_SHELLY_PRO | | / x | | | | |
|
||||||
| USE_DALI | | / - | | | | |
|
| USE_DALI | | / x | | | | |
|
||||||
| USE_DINGTIAN_RELAY | | / - | | | | |
|
| USE_DINGTIAN_RELAY | | / - | | | | |
|
||||||
| USE_MATTER_DEVICE | | / x | | | | | See SetOption151 |
|
| USE_MATTER_DEVICE | | / x | | | | | See SetOption151 |
|
||||||
|
|
||||||
|
|||||||
151
CHANGELOG.md
151
CHANGELOG.md
@ -3,6 +3,147 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
## [Released]
|
## [Released]
|
||||||
|
|
||||||
|
## [14.4.0] 20241212
|
||||||
|
- Release Rudolph
|
||||||
|
|
||||||
|
## [14.3.0.7] 20241212
|
||||||
|
### Added
|
||||||
|
- Support for TM1640 based IoTTimer by Stefan Oskamp (#21376)
|
||||||
|
- Command `SetOption161 1` to disable display of state text (#22515)
|
||||||
|
- ESP32 new BLE filters by name and minimum RSSI (#22530)
|
||||||
|
- ESP32 Hybrid compile take custom boards settings in account (#22542)
|
||||||
|
- ESP32 ULP lp_core to Berry ULP module (#22567)
|
||||||
|
- Shelly 1 Gen3 template {"NAME":"Shelly 1 Gen3","GPIO":[0,0,0,4736,0,224,0,0,1,1,192,0,0,0,0,0,0,0,0,576,1,1],"FLAG":0,"BASE":1,"CMND":"AdcGpio3 10000,10000,4000"}
|
||||||
|
- Shelly 1PM Gen3 template {"NAME":"Shelly 1PM Gen3","GPIO":[0,32,0,4736,224,0,3200,8161,576,1,192,0,0,0,0,0,0,0,0,1,1,1],"FLAG":0,"BASE":1,"CMND":"AdcGpio3 10000,10000,4000"}
|
||||||
|
- Shelly 2PM Gen3 template {"NAME":"Shelly 2PM Gen3","GPIO":[9472,3458,576,225,4736,224,640,608,1,1,193,0,0,0,0,0,0,0,192,32,1,1],"FLAG":0,"BASE":1,"CMND":"AdcGpio4 10000,10000,4000"}
|
||||||
|
- Shelly i4 Gen3 template {"NAME":"Shelly i4 Gen3","GPIO":[0,0,0,4736,32,195,194,193,1,1,192,0,0,0,0,0,0,0,0,0,1,1],"FLAG":0,"BASE":1,"CMND":"AdcGpio3 10000,10000,4000}
|
||||||
|
- Show Active Power Total with any multi-phase energy monitoring (#22579)
|
||||||
|
- Command `SetOption162 1` to disable adding export energy to energy today (#22578)
|
||||||
|
- ESP32 support for WPA2/3 Enterprise conditional in core v3.1.0.241206 (#22600)
|
||||||
|
- Support for Sonoff POWCT Energy Export Active (#22596)
|
||||||
|
|
||||||
|
### Breaking Changed
|
||||||
|
- ESP32 ArtNet switches from GRB to RGB encoding (#22556)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- ESP32 max number of supported switches/buttons/relays from 28 to 32
|
||||||
|
- ESP32 max number of interlocks from 14 to 16
|
||||||
|
- ESP32 Platform from 2024.11.30 to 2024.11.31, Framework (Arduino Core) from v3.1.0.241030 to v3.1.0.241117 and IDF to 5.3.1.241024 (#22504)
|
||||||
|
- Prevent active BLE operations with unencrypted MI-format beacons (#22453)
|
||||||
|
- ESP32 replaced NeoPixelBus with TasmotaLED (#22556)
|
||||||
|
- ESP32 Platform from 2024.11.31 to 2024.12.30, Framework (Arduino Core) from v3.1.0.241117 to v3.1.0.241206 and IDF to 5.3.2 (#22600)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- ESP32 upgrade by file upload response based on file size (#22500)
|
||||||
|
- Wrong GUI Module and Template drop down list indexes regression
|
||||||
|
- Use HTML escape on File System Edit File load (#22492)
|
||||||
|
- Magic switch applying masking window to any power change (#22535)
|
||||||
|
- Shift595 output offsets and restart relay toggles
|
||||||
|
- Shutter wrong power ON state (#22548)
|
||||||
|
- ESP32-C2 TasmotaLED from not present I2S to SPI (#22575)
|
||||||
|
- KNX Scenes index change regression from v14.2.0.4 (#22405)
|
||||||
|
- Add GUI submenu headers and refresh configuration button text (#22592)
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
## [14.3.0.6] 20241116
|
||||||
|
### Added
|
||||||
|
- Add command ``WebColor20`` to control color of Button when Off
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Matter provisioning with matter.js controller (#22470)
|
||||||
|
- Prevent crashing when `display.ini` is missing end `#` (#22471)
|
||||||
|
|
||||||
|
## [14.3.0.5] 20241111
|
||||||
|
### Added
|
||||||
|
- ESP32 MI32 legacy add config operations (#22458)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Redesign GUI adding feedback to buttons, shutters and lights
|
||||||
|
- Use command `WebButton1` to change GUI shutter 1 name
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Command ``SetOption161 1`` to disable web page slider updates by commands
|
||||||
|
|
||||||
|
## [14.3.0.4] 20241111
|
||||||
|
### Added
|
||||||
|
- DALI command `DaliGroupSliders 0..16` to show GUI group sliders with feedback disabling `DaliLight`
|
||||||
|
- Support for I2C over Serial (#22444)
|
||||||
|
- Support KNX for scripts (#22429)
|
||||||
|
- Support deep sleep (standby) for VL53L0X (#22441)
|
||||||
|
- Support for MS5837 pressure and temperature sensor (#22376)
|
||||||
|
- Berry add I2C read16/write16 supporting Little Endian (#22448)
|
||||||
|
- Berry drivers for PCA9535 (generic and in SenseCAP D1) (#22451)
|
||||||
|
- Shelly DALI Dimmer Gen3 template {"NAME":"Shelly DALI Dimmer Gen3","GPIO":[34,4736,0,3840,11360,11392,128,129,0,1,576,0,0,0,0,0,0,0,0,1,1,1],"FLAG":0,"BASE":1,"CMND":"AdcGpio1 10000,10000,4000}
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- AHT1X/AHT2X/AHT3X ready for virtual I2C (#22427)
|
||||||
|
- SGP4X ready for virtual I2C (#22427)
|
||||||
|
- SCD40 reduce logging levels (#22443)
|
||||||
|
- SCD40 ready for virtual I2C (#22443)
|
||||||
|
- Unit (k)VAr(h) to (k)var(h) (#22435)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- ESP32-S3 UART output mode for Tx (#22426)
|
||||||
|
- Mitsubishi Electric HVAC Standby Stage for MiElHVAC (#22430)
|
||||||
|
- FUNC_COMMAND linked list command buffer corruption by shutter driver
|
||||||
|
- ESP32, ESP32-S2 and ESP32-S3 re-enable touch buttons (#22446)
|
||||||
|
|
||||||
|
## [14.3.0.3] 20241031
|
||||||
|
### Added
|
||||||
|
- Support for I2C over Serial, preliminary stub (#22388)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- ESP32 Platform from 2024.10.30 to 2024.11.30, Framework (Arduino Core) from v3.1.0.241023 to v3.1.0.241030 and IDF to 5.3.1.241024 (#22384)
|
||||||
|
- ESP32 LVGL library from v9.2.0 to v9.2.2 (#22385)
|
||||||
|
- Refactored `i2c_enabled` as array (#22387)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- ESP32 Arduino Core IPv6 zones used by Matter (#22378)
|
||||||
|
|
||||||
|
## [14.3.0.2] 20241030
|
||||||
|
### Added
|
||||||
|
- DALI command `DaliGear` to set max found gear to speed up scan response
|
||||||
|
- DALI command `DaliGroup` to add gear to groups
|
||||||
|
- DALI command `DaliTarget` to set light control broadcast, group number or gear number
|
||||||
|
- Mitsubishi Electric HVAC Operation time for MiElHVAC (#22334)
|
||||||
|
- Mitsubishi Electric HVAC Outdoor Temperature for MiElHVAC (#22345)
|
||||||
|
- Mitsubishi Electric HVAC Compressor Frequency for MiElHVAC (#22347)
|
||||||
|
- SolaxX1 Meter mode (#22330)
|
||||||
|
- DALI inverted signal configuration using GPIO DALI RX_i/TX_i
|
||||||
|
- Support for Shelly DALI Dimmer Gen3 (See tips and template in file xdrv_75_dali.ino)
|
||||||
|
- HASPmota `haspmota.get_pages()` to get the sorted list of pages (#22358)
|
||||||
|
- Support for US AQI and EPA AQI in PMS5003x sensors (#22294)
|
||||||
|
- HLK-LD2410 Engineering mode (#21880)
|
||||||
|
- Support for HLK-LD2410S 24GHz smart wave motion sensor (#22253)
|
||||||
|
- Mitsubishi Electric HVAC Auto Clear Remote Temp for MiElHVAC (#22370)
|
||||||
|
- Command ``SetOption161 1`` to disable web page slider updates by commands
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- DALI renamed commands `DaliCommission` to `DaliScan` and `DaliWeb` to `DaliLight`
|
||||||
|
- DALI set Tasmota light control as default
|
||||||
|
- ESP32 Framework (Arduino Core) from v3.1.0.241015 to v3.1.0.241023 (#22351)
|
||||||
|
- Shutter optimized behavior to publish shutter data with sensor request (#22353)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Ethernet on -DFRAMEWORK_ARDUINO_ITEAD framework regression from v14.3.0 (#22367)
|
||||||
|
- Alexa Hue with multiple devices (#22383)
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- DALI inverted signal configuration using compile time defines
|
||||||
|
|
||||||
|
## [14.3.0.1] 20241022
|
||||||
|
### Added
|
||||||
|
- BLE track devices with RPA (#22300)
|
||||||
|
- DALI support for short addresses and groups
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- ESP32 platform update from 2024.09.30 to 2024.10.30 and Framework (Arduino Core) from v3.1.0.240926 to v3.1.0.241015 (#22299)
|
||||||
|
- HASPmota support for page delete and object updates (#22311)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- EQ3 TRV firmware version 1.46 fails if the default true is used in subscribe on the notify characteristic (#22328)
|
||||||
|
|
||||||
## [14.3.0] 20241015
|
## [14.3.0] 20241015
|
||||||
- Release Robert
|
- Release Robert
|
||||||
|
|
||||||
@ -16,11 +157,11 @@ All notable changes to this project will be documented in this file.
|
|||||||
- Command ``DaliSend <address>|<address+256>,<command>`` to send command (address+256 is repeat) on DALI bus
|
- Command ``DaliSend <address>|<address+256>,<command>`` to send command (address+256 is repeat) on DALI bus
|
||||||
- Command ``DaliQuery <address>|<address+256>,<command>`` to send command (address+256 is repeat) on DALI bus and wait up to DALI_TIMEOUT ms for response
|
- Command ``DaliQuery <address>|<address+256>,<command>`` to send command (address+256 is repeat) on DALI bus and wait up to DALI_TIMEOUT ms for response
|
||||||
- Berry Serial `config` to change parity on-the-fly for RS-485 (#22285)
|
- Berry Serial `config` to change parity on-the-fly for RS-485 (#22285)
|
||||||
- Misubishi Electric HVAC Heat/Dry/Cool Auto operation mode (#22216)
|
- Mitsubishi Electric HVAC Heat/Dry/Cool Auto operation mode (#22216)
|
||||||
- Misubishi Electric HVAC Bridge to HomeBridge/Homekit locally (#22236)
|
- Mitsubishi Electric HVAC Bridge to HomeBridge/Homekit locally (#22236)
|
||||||
- Misubishi Electric HVAC Air Direction Control (#22241)
|
- Mitsubishi Electric HVAC Air Direction Control (#22241)
|
||||||
- Misubishi Electric HVAC prohibit function (#22269)
|
- Mitsubishi Electric HVAC prohibit function (#22269)
|
||||||
- Misubishi Electric HVAC compressor map and operation power and energy (#22290)
|
- Mitsubishi Electric HVAC compressor map and operation power and energy (#22290)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- ESP32 platform update from 2024.09.10 to 2024.09.30 and Framework (Arduino Core) from v3.0.5 to v3.1.0.240926 (#22203)
|
- ESP32 platform update from 2024.09.10 to 2024.09.30 and Framework (Arduino Core) from v3.0.5 to v3.1.0.240926 (#22203)
|
||||||
|
|||||||
@ -14,7 +14,7 @@ If you like **Tasmota**, give it a star, or fork it and contribute!
|
|||||||
[](https://github.com/arendst/Tasmota/network)
|
[](https://github.com/arendst/Tasmota/network)
|
||||||
[](https://paypal.me/tasmota)
|
[](https://paypal.me/tasmota)
|
||||||
|
|
||||||
See [CHANGELOG.md](https://github.com/arendst/Tasmota/blob/development/tasmota/CHANGELOG.md) for changes since last release.
|
See [CHANGELOG.md](https://github.com/arendst/Tasmota/blob/development/CHANGELOG.md) for changes since last release.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
|||||||
@ -128,5 +128,6 @@ Index | Define | Driver | Device | Address(es) | Bus2 | Descrip
|
|||||||
88 | USE_QMP6988 | xsns_28 | QMP6988 | 0x56, 0x70 | Yes | Pressure and temperature sensor
|
88 | USE_QMP6988 | xsns_28 | QMP6988 | 0x56, 0x70 | Yes | Pressure and temperature sensor
|
||||||
89 | USE_HX711_M5SCALES | xsns_34 | M5SCALES | 0x26 | Yes | M5Unit (Mini)Scales(HX711 STM32) U177
|
89 | USE_HX711_M5SCALES | xsns_34 | M5SCALES | 0x26 | Yes | M5Unit (Mini)Scales(HX711 STM32) U177
|
||||||
90 | USE_RX8010 | xdrv_56 | RX8010 | 0x32 | Yes | RX8010 RTC from IOTTIMER
|
90 | USE_RX8010 | xdrv_56 | RX8010 | 0x32 | Yes | RX8010 RTC from IOTTIMER
|
||||||
|
91 | USE_MS5837 | xsns_116 | MS5837 | 0x76 | | Pressure and temperature sensor
|
||||||
|
|
||||||
NOTE: Bus2 supported on ESP32 only.
|
NOTE: Bus2 supported on ESP32 only.
|
||||||
|
|||||||
165
RELEASENOTES.md
165
RELEASENOTES.md
@ -36,9 +36,9 @@ While fallback or downgrading is common practice it was never supported due to S
|
|||||||
|
|
||||||
This release will be supported from ESP8266/Arduino library Core version **2.7.8** due to reported security and stability issues on previous Core version. This will also support gzipped binaries.
|
This release will be supported from ESP8266/Arduino library Core version **2.7.8** due to reported security and stability issues on previous Core version. This will also support gzipped binaries.
|
||||||
|
|
||||||
This release will be supported from ESP32/Arduino library Core version **v3.1.0.240926**.
|
This release will be supported from ESP32/Arduino library Core version **v3.1.0.241206**.
|
||||||
|
|
||||||
Support of ESP8266 Core versions before 2.7.8 and ESP32 Core versions before v3.1.0.240926 have been removed.
|
Support of ESP8266 Core versions before 2.7.8 and ESP32 Core versions before v3.1.0.241206 have been removed.
|
||||||
|
|
||||||
## Support of TLS
|
## Support of TLS
|
||||||
|
|
||||||
@ -75,12 +75,12 @@ Latest released binaries can be downloaded from
|
|||||||
- http://ota.tasmota.com/tasmota/release
|
- http://ota.tasmota.com/tasmota/release
|
||||||
|
|
||||||
Historical binaries can be downloaded from
|
Historical binaries can be downloaded from
|
||||||
- http://ota.tasmota.com/tasmota/release-14.3.0
|
- http://ota.tasmota.com/tasmota/release-14.4.0
|
||||||
|
|
||||||
The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin.gz``
|
The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin.gz``
|
||||||
|
|
||||||
### ESP32, ESP32-C2, ESP32-C3, ESP32-C6, ESP32-S2 and ESP32-S3 based
|
### ESP32, ESP32-C2, ESP32-C3, ESP32-C6, ESP32-S2 and ESP32-S3 based
|
||||||
The following binary downloads have been compiled with ESP32/Arduino library core version **v3.1.0.240926**.
|
The following binary downloads have been compiled with ESP32/Arduino library core version **v3.1.0.241206**.
|
||||||
|
|
||||||
- **tasmota32.bin** = The Tasmota version with most drivers including additional sensors and KNX for 4M+ flash. **RECOMMENDED RELEASE BINARY**
|
- **tasmota32.bin** = The Tasmota version with most drivers including additional sensors and KNX for 4M+ flash. **RECOMMENDED RELEASE BINARY**
|
||||||
- **tasmota32solo1.bin** = The Tasmota version with most drivers including additional sensors and KNX for single core ESP32 and 4M+ flash.
|
- **tasmota32solo1.bin** = The Tasmota version with most drivers including additional sensors and KNX for single core ESP32 and 4M+ flash.
|
||||||
@ -104,7 +104,7 @@ Latest released binaries can be downloaded from
|
|||||||
- https://ota.tasmota.com/tasmota32/release
|
- https://ota.tasmota.com/tasmota32/release
|
||||||
|
|
||||||
Historical binaries can be downloaded from
|
Historical binaries can be downloaded from
|
||||||
- https://ota.tasmota.com/tasmota32/release-14.3.0
|
- https://ota.tasmota.com/tasmota32/release-14.4.0
|
||||||
|
|
||||||
The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasmota.com/tasmota32/release/tasmota32.bin``
|
The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasmota.com/tasmota32/release/tasmota32.bin``
|
||||||
|
|
||||||
@ -114,96 +114,83 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
|
|||||||
|
|
||||||
[Complete list](BUILDS.md) of available feature and sensors.
|
[Complete list](BUILDS.md) of available feature and sensors.
|
||||||
|
|
||||||
## Changelog v14.3.0 Robert
|
## Changelog v14.4.0 Rudolph
|
||||||
### Added
|
### Added
|
||||||
- Command ``SetOption69 1`` to enable Serial Bridge inverted Receive [#22000](https://github.com/arendst/Tasmota/issues/22000)
|
- Command `WebColor20` to control color of Button when Off
|
||||||
- Command ``DaliWeb 1`` to enable light control for DALI broadcast address
|
- Command `SetOption161 1` to disable display of state text [#22515](https://github.com/arendst/Tasmota/issues/22515)
|
||||||
- Command ``DaliSend <address>|<address+256>,<command>`` to send command (address+256 is repeat) on DALI bus
|
- Command `SetOption162 1` to disable adding export energy to energy today [#22578](https://github.com/arendst/Tasmota/issues/22578)
|
||||||
- Command ``DaliQuery <address>|<address+256>,<command>`` to send command (address+256 is repeat) on DALI bus and wait up to DALI_TIMEOUT ms for response
|
- DALI support for short addresses (gear) and groups
|
||||||
- HX711 optional calibration precision option on command ``Sensor34 2 <weight in gram> <precision>`` where `<precision>` is 1 to 20 [#13983](https://github.com/arendst/Tasmota/issues/13983)
|
- DALI command `DaliGear` to set max found gear to speed up scan response
|
||||||
- ESP8266 support for one-wire M1601 temperature sensor on DS18x20 GPIO [#21376](https://github.com/arendst/Tasmota/issues/21376)
|
- DALI command `DaliGroup` to add gear to groups
|
||||||
- ESP8266 support for I2C CLK on GPIO16 [#22199](https://github.com/arendst/Tasmota/issues/22199)
|
- DALI command `DaliTarget` to set light control broadcast, group number or gear number
|
||||||
- Support for I2C M5Unit (Mini)Scales using HX711 driver
|
- DALI command `DaliGroupSliders 0..16` to show GUI group sliders with feedback disabling `DaliLight`
|
||||||
- Support for DALI on ESP8266
|
- DALI inverted signal configuration using GPIO DALI RX_i/TX_i
|
||||||
- Support for RX8010 RTC as used in IOTTIMER [#21376](https://github.com/arendst/Tasmota/issues/21376)
|
- Support for I2C over Serial [#22444](https://github.com/arendst/Tasmota/issues/22444)
|
||||||
- Support for BL0906 up to 6 channel energy monitor as used in Athom EM2/EM6 [#22167](https://github.com/arendst/Tasmota/issues/22167)
|
- Support KNX for scripts [#22429](https://github.com/arendst/Tasmota/issues/22429)
|
||||||
- Support for Sonoff SPM v1.3.0 [#13447](https://github.com/arendst/Tasmota/issues/13447)
|
- Support deep sleep (standby) for VL53L0X [#22441](https://github.com/arendst/Tasmota/issues/22441)
|
||||||
- Energy command ``PowerSet 60,230`` to calibrate both Current and Power with known resistive load of 60W at 230V using calibrated Voltage
|
- Support for Shelly DALI Dimmer Gen3
|
||||||
- Energy command ``CurrentSet 60,230`` to calibrate both Power and Current with known resistive load of 60W at 230V using calibrated Voltage
|
- Support for HLK-LD2410S 24GHz smart wave motion sensor [#22253](https://github.com/arendst/Tasmota/issues/22253)
|
||||||
- ESP8266 experimental support for second I2C bus
|
- Support for US AQI and EPA AQI in PMS5003x sensors [#22294](https://github.com/arendst/Tasmota/issues/22294)
|
||||||
- MQTT warning if trying to connect without TLS on a port that normally uses TLS [#22175](https://github.com/arendst/Tasmota/issues/22175)
|
- Support for MS5837 pressure and temperature sensor [#22376](https://github.com/arendst/Tasmota/issues/22376)
|
||||||
- Energy Log level 4 message when (Calculated) Apparent Power is less than Active Power indicating wrong calibration [#20653](https://github.com/arendst/Tasmota/issues/20653)
|
- Support for TM1640 based IoTTimer by Stefan Oskamp [#21376](https://github.com/arendst/Tasmota/issues/21376)
|
||||||
- Support nexus protocol and calculation of separation limit to rc-switch library [#21886](https://github.com/arendst/Tasmota/issues/21886)
|
- Support for Sonoff POWCT Energy Export Active [#22596](https://github.com/arendst/Tasmota/issues/22596)
|
||||||
- KNX additional KnxTx functions and define KNX_USE_DPT9 [#22071](https://github.com/arendst/Tasmota/issues/22071)
|
- HLK-LD2410 Engineering mode [#21880](https://github.com/arendst/Tasmota/issues/21880)
|
||||||
- SML multi TRX line [#22056](https://github.com/arendst/Tasmota/issues/22056)
|
- Mitsubishi Electric HVAC Operation time for MiElHVAC [#22334](https://github.com/arendst/Tasmota/issues/22334)
|
||||||
- Misubishi Electric HVAC Heat/Dry/Cool Auto operation mode [#22216](https://github.com/arendst/Tasmota/issues/22216)
|
- Mitsubishi Electric HVAC Outdoor Temperature for MiElHVAC [#22345](https://github.com/arendst/Tasmota/issues/22345)
|
||||||
- Misubishi Electric HVAC Bridge to HomeBridge/Homekit locally [#22236](https://github.com/arendst/Tasmota/issues/22236)
|
- Mitsubishi Electric HVAC Compressor Frequency for MiElHVAC [#22347](https://github.com/arendst/Tasmota/issues/22347)
|
||||||
- Misubishi Electric HVAC Air Direction Control [#22241](https://github.com/arendst/Tasmota/issues/22241)
|
- Mitsubishi Electric HVAC Auto Clear Remote Temp for MiElHVAC [#22370](https://github.com/arendst/Tasmota/issues/22370)
|
||||||
- Misubishi Electric HVAC prohibit function [#22269](https://github.com/arendst/Tasmota/issues/22269)
|
- SolaxX1 Meter mode [#22330](https://github.com/arendst/Tasmota/issues/22330)
|
||||||
- Misubishi Electric HVAC compressor map and operation power and energy [#22290](https://github.com/arendst/Tasmota/issues/22290)
|
- Show Active Power Total with any multi-phase energy monitoring [#22579](https://github.com/arendst/Tasmota/issues/22579)
|
||||||
- Zigbee Koenkk firmware 20240710 for Sonoff Zigbee ZBPro [#22076](https://github.com/arendst/Tasmota/issues/22076)
|
- ESP32 support for WPA2/3 Enterprise conditional in core v3.1.0.241206 [#22600](https://github.com/arendst/Tasmota/issues/22600)
|
||||||
- Berry Zigbee improvements to prepare Matter [#22083](https://github.com/arendst/Tasmota/issues/22083)
|
- ESP32 ULP lp_core to Berry ULP module (#22567)[#22567](https://github.com/arendst/Tasmota/issues/22567)
|
||||||
- Berry virtual Energy driver [#22134](https://github.com/arendst/Tasmota/issues/22134)
|
- ESP32 new BLE filters by name and minimum RSSI [#22530](https://github.com/arendst/Tasmota/issues/22530)
|
||||||
- Berry improve `int64` constructor [#22172](https://github.com/arendst/Tasmota/issues/22172)
|
- ESP32 Hybrid compile take custom boards settings in account [#22542](https://github.com/arendst/Tasmota/issues/22542)
|
||||||
- Berry Serial `config` to change parity on-the-fly for RS-485 [#22285](https://github.com/arendst/Tasmota/issues/22285)
|
- ESP32 MI32 legacy add config operations [#22458](https://github.com/arendst/Tasmota/issues/22458)
|
||||||
- LVGL port `colorwheel` from LVGL 8 [#22244](https://github.com/arendst/Tasmota/issues/22244)
|
- BLE track devices with RPA [#22300](https://github.com/arendst/Tasmota/issues/22300)
|
||||||
- HASPmota `cpicker` and `msgbox` [#22244](https://github.com/arendst/Tasmota/issues/22244)
|
- Berry add I2C read16/write16 supporting Little Endian [#22448](https://github.com/arendst/Tasmota/issues/22448)
|
||||||
- Matter support for Zigbee Temperature, Humidity and Pressure sensors [#22084](https://github.com/arendst/Tasmota/issues/22084)
|
- Berry drivers for PCA9535 (generic and in SenseCAP D1) [#22451](https://github.com/arendst/Tasmota/issues/22451)
|
||||||
- Matter support for Zigbee Occupancy and Light 0/1/2 (OnOff / Dimmer / White Color Temperature) [#22110](https://github.com/arendst/Tasmota/issues/22110)
|
- HASPmota `haspmota.get_pages()` to get the sorted list of pages [#22358](https://github.com/arendst/Tasmota/issues/22358)
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
- Berry make `energy` modules changes from #21887 backwards compatible [#22046](https://github.com/arendst/Tasmota/issues/22046)
|
- ESP32 ArtNet switches from GRB to RGB encoding [#22556](https://github.com/arendst/Tasmota/issues/22556)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- ESP8266 platform update from 2024.06.00 to 2024.09.00 and Framework (Arduino Core) from v2.7.7 to v2.7.8 [#22199](https://github.com/arendst/Tasmota/issues/22199)
|
- ESP32 Platform from 2024.09.30 to 2024.12.30, Framework (Arduino Core) from v3.1.0.240926 to v3.1.0.241206 and IDF to 5.3.2 [#22600](https://github.com/arendst/Tasmota/issues/22600)
|
||||||
- ESP32 platform update from 2024.08.10 to 2024.09.30 and Framework (Arduino Core) from v3.0.4 to v3.1.0.240926 [#22203](https://github.com/arendst/Tasmota/issues/22203)
|
- ESP32 LVGL library from v9.2.0 to v9.2.2 [#22385](https://github.com/arendst/Tasmota/issues/22385)
|
||||||
- ESP32 LVGL library from v9.1.0 to v9.2.0 [#22031](https://github.com/arendst/Tasmota/issues/22031)
|
- ESP32 replaced NeoPixelBus with TasmotaLED [#22556](https://github.com/arendst/Tasmota/issues/22556)
|
||||||
- GPIOViewer from v1.5.5 to v1.5.6
|
- Redesign GUI adding feedback to buttons, shutters and lights
|
||||||
- Add command entered to command error and command unknown message
|
- Add GUI submenu headers and refresh configuration button text (#22592)
|
||||||
- Refactored I2C drivers HTU21, BH1750, SHT3x, iAQ and HYT
|
- Use command `WebButton1` to change GUI shutter 1 name
|
||||||
- Energy BL09xx command ``CurrentSet`` input changed from Ampere to milliAmpere
|
- Unit (k)VAr(h) to (k)var(h) [#22435](https://github.com/arendst/Tasmota/issues/22435)
|
||||||
- Command ``DaliDimmer`` range from 0..254 to 0..100
|
- AHT1X/AHT2X/AHT3X ready for virtual I2C [#22427](https://github.com/arendst/Tasmota/issues/22427)
|
||||||
- Energy force Apparent Power equals Active Power when (Calculated) Apparent Power is less than Active Power [#20653](https://github.com/arendst/Tasmota/issues/20653)
|
- SGP4X ready for virtual I2C [#22427](https://github.com/arendst/Tasmota/issues/22427)
|
||||||
- Refactor and fix PID sensor (PID_USE_LOCAL_SENSOR) read race condition [#22162](https://github.com/arendst/Tasmota/issues/22162)
|
- SCD40 reduce logging levels [#22443](https://github.com/arendst/Tasmota/issues/22443)
|
||||||
- SCD30 Lowered I2C clock from 100k to 50k [#15438](https://github.com/arendst/Tasmota/issues/15438)
|
- SCD40 ready for virtual I2C [#22443](https://github.com/arendst/Tasmota/issues/22443)
|
||||||
- HASPmota `delete` instead of `delete()` [#22245](https://github.com/arendst/Tasmota/issues/22245)
|
- Refactored `i2c_enabled` as array [#22387](https://github.com/arendst/Tasmota/issues/22387)
|
||||||
|
- DALI renamed commands `DaliCommission` to `DaliScan` and `DaliWeb` to `DaliLight`
|
||||||
|
- DALI set Tasmota light control as default
|
||||||
|
- Shutter optimized behavior to publish shutter data with sensor request [#22353](https://github.com/arendst/Tasmota/issues/22353)
|
||||||
|
- Prevent active BLE operations with unencrypted MI-format beacons [#22453](https://github.com/arendst/Tasmota/issues/22453)
|
||||||
|
- ESP32 max number of supported switches/buttons/relays from 28 to 32
|
||||||
|
- ESP32 max number of interlocks from 14 to 16
|
||||||
|
- HASPmota support for page delete and object updates [#22311](https://github.com/arendst/Tasmota/issues/22311)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- DALI received data decoding
|
- FUNC_COMMAND linked list command buffer corruption by shutter driver
|
||||||
- Compilation exception when metrics not found [#22170](https://github.com/arendst/Tasmota/issues/22170)
|
- Shift595 output offsets and restart relay toggles
|
||||||
- Crash when calling TasmotaSerial destructor when initialized with incorrect arguments [#22036](https://github.com/arendst/Tasmota/issues/22036)
|
- Use HTML escape on File System Edit File load [#22492](https://github.com/arendst/Tasmota/issues/22492)
|
||||||
- Energy calculation [#20653](https://github.com/arendst/Tasmota/issues/20653)
|
- Prevent crashing when `display.ini` is missing end `#` [#22471](https://github.com/arendst/Tasmota/issues/22471)
|
||||||
- SML trx pin error [#22119](https://github.com/arendst/Tasmota/issues/22119)
|
- KNX Scenes index change regression from v14.2.0.4 [#22405](https://github.com/arendst/Tasmota/issues/22405)
|
||||||
- Shutter timing registers overflow [#21966](https://github.com/arendst/Tasmota/issues/21966)
|
- Magic switch applying masking window to any power change [#22535](https://github.com/arendst/Tasmota/issues/22535)
|
||||||
- Shutter missing HOLD on shutterbutton [#22108](https://github.com/arendst/Tasmota/issues/22108)
|
- Shutter wrong power ON state [#22548](https://github.com/arendst/Tasmota/issues/22548)
|
||||||
- Shutter remaining issues on shutterinvert [#22120](https://github.com/arendst/Tasmota/issues/22120)
|
- Alexa Hue with multiple devices [#22383](https://github.com/arendst/Tasmota/issues/22383)
|
||||||
- PZEM continue energy monitoring when one phase fails [#21968](https://github.com/arendst/Tasmota/issues/21968)
|
- Mitsubishi Electric HVAC Standby Stage for MiElHVAC [#22430](https://github.com/arendst/Tasmota/issues/22430)
|
||||||
- BearSSL panic on ESP8266 in rare conditions [#22017](https://github.com/arendst/Tasmota/issues/22017)
|
- EQ3 TRV firmware version 1.46 fails if the default true is used in subscribe on the notify characteristic [#22328](https://github.com/arendst/Tasmota/issues/22328)
|
||||||
- ModbusBridge request and response logic [#22075](https://github.com/arendst/Tasmota/issues/22075)
|
- Ethernet on -DFRAMEWORK_ARDUINO_ITEAD framework regression from v14.3.0 [#22367](https://github.com/arendst/Tasmota/issues/22367)
|
||||||
- Sonoff WTS01 temperature sensor shows incorrect negative temperature [#19373](https://github.com/arendst/Tasmota/issues/19373)
|
- ESP32 Upgrade by file upload response based on file size [#22500](https://github.com/arendst/Tasmota/issues/22500)
|
||||||
- Autoconf prevent 'init.bat' from stopping on empty lines [#22158](https://github.com/arendst/Tasmota/issues/22158)
|
- ESP32 Arduino Core IPv6 zones used by Matter [#22378](https://github.com/arendst/Tasmota/issues/22378)
|
||||||
- Zigbee extend timeout for MCU reboot from 5s to 10s [#22009](https://github.com/arendst/Tasmota/issues/22009)
|
- ESP32, ESP32-S2 and ESP32-S3 re-enable touch buttons [#22446](https://github.com/arendst/Tasmota/issues/22446)
|
||||||
- Zigbee avoid disabling console serial on ESP32 and improved log messages [#22082](https://github.com/arendst/Tasmota/issues/22082)
|
- ESP32-S3 UART output mode for Tx [#22426](https://github.com/arendst/Tasmota/issues/22426)
|
||||||
- Zigbee flashing CC2562P with latest firmware [#22117](https://github.com/arendst/Tasmota/issues/22117)
|
- Matter provisioning with matter.js controller [#22470](https://github.com/arendst/Tasmota/issues/22470)
|
||||||
- ESP32 Range Extender compile error with core 3.x [#22205](https://github.com/arendst/Tasmota/issues/22205)
|
|
||||||
- ESP32 DALI compile error with core 3.x [#22214](https://github.com/arendst/Tasmota/issues/22214)
|
|
||||||
- ESP32 Ethernet using EthClockMode 3 [#22248](https://github.com/arendst/Tasmota/issues/22248)
|
|
||||||
- ESP32 disable SPI DMA for uDisplay (broken since esp-idf 5.3 (core 3.1.0)) [#22264](https://github.com/arendst/Tasmota/issues/22264)
|
|
||||||
- Berry avoid `readbytes()` from crashing when file is too large [#22057](https://github.com/arendst/Tasmota/issues/22057)
|
|
||||||
- Berry energy missing attributes [#22116](https://github.com/arendst/Tasmota/issues/22116)
|
|
||||||
- Berry I2C to prepare M5Stack I2C STM32 based devices [#22143](https://github.com/arendst/Tasmota/issues/22143)
|
|
||||||
- Berry improve `persist` dirty data handling [#22246](https://github.com/arendst/Tasmota/issues/22246)
|
|
||||||
- ESP32-S3 uDisplay force cache writes to RGB display [#22222](https://github.com/arendst/Tasmota/issues/22222)
|
|
||||||
- LVGL Added OpenHASP icons to font `montserrat-28` [#22048](https://github.com/arendst/Tasmota/issues/22048)
|
|
||||||
- LVGL compilation of lv_menu [#22188](https://github.com/arendst/Tasmota/issues/22188)
|
|
||||||
- HASPmota broken `changed` event [#22194](https://github.com/arendst/Tasmota/issues/22194)
|
|
||||||
- HASPmota error when page '1' is not defined [#22220](https://github.com/arendst/Tasmota/issues/22220)
|
|
||||||
- Matter fixed UI bug when no endpoints configured [#22008](https://github.com/arendst/Tasmota/issues/22008)
|
|
||||||
- Matter fix when Rules are disabled [#22016](https://github.com/arendst/Tasmota/issues/22016)
|
|
||||||
- Matter fail to report Shutter status if no shutter is configured in Tasmota [#22049](https://github.com/arendst/Tasmota/issues/22049)
|
|
||||||
- Matter fix Waterleak broken after Berry solidification optimisation #21885 [#22052](https://github.com/arendst/Tasmota/issues/22052)
|
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- ESP8266 Analog input support using energy driver as only one channel is available
|
|
||||||
- Berry remove reuse of methods for interface-like code reuse #21500 [#22055](https://github.com/arendst/Tasmota/issues/22055)
|
|
||||||
- Berry Zigbee removed test code [#22263](https://github.com/arendst/Tasmota/issues/22263)
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
# Templates
|
# Templates
|
||||||
|
|
||||||
Find below the available templates as of October 2024. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates)
|
Find below the available templates as of December 2024. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates)
|
||||||
|
|
||||||
## Adapter Board
|
## Adapter Board
|
||||||
```
|
```
|
||||||
|
|||||||
@ -59,7 +59,7 @@ typedef enum WiFiPhyMode
|
|||||||
class WiFiHelper {
|
class WiFiHelper {
|
||||||
public:
|
public:
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
static wl_status_t begin(const char* wpa2_ssid, wpa2_auth_method_t method, const char* wpa2_identity=NULL, const char* wpa2_username=NULL, const char *wpa2_password=NULL, const char* ca_pem=NULL, const char* client_crt=NULL, const char* client_key=NULL, int32_t channel=0, const uint8_t* bssid=0, bool connect=true);
|
static wl_status_t begin(const char* wpa2_ssid, wpa2_auth_method_t method, const char* wpa2_identity=NULL, const char* wpa2_username=NULL, const char *wpa2_password=NULL, const char* ca_pem=NULL, const char* client_crt=NULL, const char* client_key=NULL, int ttls_phase2_type=-1, int32_t channel=0, const uint8_t* bssid=0, bool connect=true);
|
||||||
#endif
|
#endif
|
||||||
static wl_status_t begin(const char* ssid, const char *passphrase = NULL, int32_t channel = 0, const uint8_t* bssid = NULL, bool connect = true);
|
static wl_status_t begin(const char* ssid, const char *passphrase = NULL, int32_t channel = 0, const uint8_t* bssid = NULL, bool connect = true);
|
||||||
static wl_status_t begin(char* ssid, char *passphrase = NULL, int32_t channel = 0, const uint8_t* bssid = NULL, bool connect = true);
|
static wl_status_t begin(char* ssid, char *passphrase = NULL, int32_t channel = 0, const uint8_t* bssid = NULL, bool connect = true);
|
||||||
@ -94,4 +94,4 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // WIFIHELPER_H
|
#endif // WIFIHELPER_H
|
||||||
|
|||||||
@ -34,12 +34,14 @@ ip_addr_t dns_save6[DNS_MAX_SERVERS] = {}; // IPv6 DNS servers
|
|||||||
#include "tasmota_options.h"
|
#include "tasmota_options.h"
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
|
|
||||||
wl_status_t WiFiHelper::begin(const char* wpa2_ssid, wpa2_auth_method_t method, const char* wpa2_identity, const char* wpa2_username, const char *wpa2_password, const char* ca_pem, const char* client_crt, const char* client_key, int32_t channel, const uint8_t* bssid, bool connect) {
|
#if CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT
|
||||||
|
wl_status_t WiFiHelper::begin(const char *wpa2_ssid, wpa2_auth_method_t method, const char *wpa2_identity, const char *wpa2_username, const char *wpa2_password, const char *ca_pem, const char *client_crt, const char *client_key, int ttls_phase2_type, int32_t channel, const uint8_t *bssid, bool connect) {
|
||||||
WiFiHelper::scrubDNS();
|
WiFiHelper::scrubDNS();
|
||||||
wl_status_t ret = WiFi.begin(wpa2_ssid, method, wpa2_identity, wpa2_username, wpa2_password, ca_pem, client_crt, client_key, channel, bssid, connect);
|
wl_status_t ret = WiFi.begin(wpa2_ssid, method, wpa2_identity, wpa2_username, wpa2_password, ca_pem, client_crt, client_key, ttls_phase2_type, channel, bssid, connect);
|
||||||
WiFiHelper::scrubDNS();
|
WiFiHelper::scrubDNS();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif // CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT
|
||||||
|
|
||||||
wl_status_t WiFiHelper::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) {
|
wl_status_t WiFiHelper::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) {
|
||||||
WiFiHelper::scrubDNS();
|
WiFiHelper::scrubDNS();
|
||||||
|
|||||||
@ -58,6 +58,10 @@
|
|||||||
|
|
||||||
#include "AudioGeneratorMIDI.h"
|
#include "AudioGeneratorMIDI.h"
|
||||||
|
|
||||||
|
#if defined(ESP32)
|
||||||
|
// Do not build, Espressif's GCC8+ has a compiler bug
|
||||||
|
#else // __GNUC__ == 8
|
||||||
|
|
||||||
#pragma GCC optimize ("O3")
|
#pragma GCC optimize ("O3")
|
||||||
|
|
||||||
#define TSF_NO_STDIO
|
#define TSF_NO_STDIO
|
||||||
@ -637,3 +641,4 @@ void AudioGeneratorMIDI::MakeStreamFromAFS(AudioFileSource *src, tsf_stream *afs
|
|||||||
afs->size = &afs_size;
|
afs->size = &afs_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //__GNUC__ == 8
|
||||||
|
|||||||
@ -21,6 +21,10 @@
|
|||||||
#ifndef _AUDIOGENERATORMIDI_H
|
#ifndef _AUDIOGENERATORMIDI_H
|
||||||
#define _AUDIOGENERATORMIDI_H
|
#define _AUDIOGENERATORMIDI_H
|
||||||
|
|
||||||
|
#if defined(ESP32)
|
||||||
|
// Do not build, Espressif's GCC8+ has a compiler bug
|
||||||
|
#else // __GNUC__ == 8
|
||||||
|
|
||||||
#include "AudioGenerator.h"
|
#include "AudioGenerator.h"
|
||||||
|
|
||||||
#define TSF_NO_STDIO
|
#define TSF_NO_STDIO
|
||||||
@ -90,7 +94,7 @@ class AudioGeneratorMIDI : public AudioGenerator
|
|||||||
unsigned long earliest_time = 0;
|
unsigned long earliest_time = 0;
|
||||||
|
|
||||||
struct tonegen_status { /* current status of a tone generator */
|
struct tonegen_status { /* current status of a tone generator */
|
||||||
bool playing; /* is it playing? */
|
bool playing; /* is it playing? */
|
||||||
char track; /* if so, which track is the note from? */
|
char track; /* if so, which track is the note from? */
|
||||||
char note; /* what note is playing? */
|
char note; /* what note is playing? */
|
||||||
char instrument; /* what instrument? */
|
char instrument; /* what instrument? */
|
||||||
@ -176,6 +180,7 @@ class AudioGeneratorMIDI : public AudioGenerator
|
|||||||
short samplesRendered[256];
|
short samplesRendered[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif //__GNUC__ == 8
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,16 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// ESP32 as of 3.x has a compiler bug in this section, with the G++ generated assembly
|
||||||
|
// being illegal. There's nothing wrong with the code here, it just looks like an
|
||||||
|
// Xtensa backend issue. Until that's fixed, no MIDI for you!
|
||||||
|
///home/earle/Arduino/libraries/ESP8266Audio/src/libtinysoundfont/tsf.h: In function 'void tsf_channel_midi_control(tsf*, int, int, int)':
|
||||||
|
// /home/earle/Arduino/libraries/ESP8266Audio/src/libtinysoundfont/tsf.h:2101:1: error: insn does not satisfy its constraints:
|
||||||
|
// 2101 | }
|
||||||
|
// | ^
|
||||||
|
|
||||||
|
#if !defined(ESP32)
|
||||||
|
|
||||||
#ifndef TSF_INCLUDE_TSF_INL
|
#ifndef TSF_INCLUDE_TSF_INL
|
||||||
#define TSF_INCLUDE_TSF_INL
|
#define TSF_INCLUDE_TSF_INL
|
||||||
|
|
||||||
@ -2149,3 +2159,5 @@ TSFDEF float tsf_channel_get_tuning(tsf* f, int channel)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif //TSF_IMPLEMENTATION
|
#endif //TSF_IMPLEMENTATION
|
||||||
|
|
||||||
|
#endif // ! ESP32
|
||||||
|
|||||||
@ -69,7 +69,7 @@ typedef struct {
|
|||||||
rmt_symbol_word_t reset_code;
|
rmt_symbol_word_t reset_code;
|
||||||
} rmt_led_strip_encoder_t;
|
} rmt_led_strip_encoder_t;
|
||||||
|
|
||||||
static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
|
static IRAM_ATTR size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
|
||||||
{
|
{
|
||||||
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
|
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
|
||||||
|
|||||||
17
lib/lib_basic/TasmotaLED/library.json
Normal file
17
lib/lib_basic/TasmotaLED/library.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "TasmotaLED",
|
||||||
|
"version": "0.1",
|
||||||
|
"keywords": [
|
||||||
|
"ws2816", "sk6812", "leds"
|
||||||
|
],
|
||||||
|
"description": "Lightweight implementation for adressable leds.",
|
||||||
|
"repository":
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/arendst/Tasmota/lib/lib_basic/TasmotaLED"
|
||||||
|
},
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": [
|
||||||
|
"espressif32"
|
||||||
|
]
|
||||||
|
}
|
||||||
237
lib/lib_basic/TasmotaLED/src/TasmotaLED.cpp
Normal file
237
lib/lib_basic/TasmotaLED/src/TasmotaLED.cpp
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
TasmotaLED.cpp - Lightweight implementation for adressable leds.
|
||||||
|
|
||||||
|
Copyright (C) 2024 Stephan Hadinger
|
||||||
|
|
||||||
|
This library is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#ifdef ESP32
|
||||||
|
|
||||||
|
#include "TasmotaLEDPusher.h"
|
||||||
|
#include "TasmotaLED.h"
|
||||||
|
|
||||||
|
// DRAM_ATTR to force in IRAM because we use this in show loop
|
||||||
|
static const DRAM_ATTR uint8_t TASMOTALED_CHANNEL_ORDERS[6][3] = {
|
||||||
|
{1, 0, 2}, // GRB (0)
|
||||||
|
{2, 0, 1}, // GBR (1)
|
||||||
|
{0, 1, 2}, // RGB (2)
|
||||||
|
{0, 2, 1}, // RBG (3)
|
||||||
|
{2, 1, 0}, // BRG (4)
|
||||||
|
{1, 2, 0} // BGR (5)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const TasmotaLED_Timing TasmotaLED_Timings[] = {
|
||||||
|
// WS2812
|
||||||
|
// RmtBit0 0x00228010 RmtBit1 0x00128020 RmtReset 0x800207D0
|
||||||
|
{
|
||||||
|
.T0H = 400,
|
||||||
|
.T0L = 850,
|
||||||
|
.T1H = 800,
|
||||||
|
.T1L = 450,
|
||||||
|
.Reset = 80000 // it is 50000 for WS2812, but for compatibility with SK6812, we raise to 80000
|
||||||
|
},
|
||||||
|
// SK6812
|
||||||
|
// RmtBit0 0x0024800C RmtBit1 0x00188018 RmtReset 0x80020C80
|
||||||
|
{
|
||||||
|
.T0H = 300,
|
||||||
|
.T0L = 900,
|
||||||
|
.T1H = 600,
|
||||||
|
.T1L = 600,
|
||||||
|
.Reset = 80000
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// enable AddLog
|
||||||
|
extern void AddLog(uint32_t loglevel, PGM_P formatP, ...);
|
||||||
|
enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE};
|
||||||
|
|
||||||
|
|
||||||
|
TasmotaLED::TasmotaLED(uint16_t type, uint16_t num_leds) :
|
||||||
|
_type(type),
|
||||||
|
_pixel_order((type >> 4) & 0x07),
|
||||||
|
_w_before(type & 0x08),
|
||||||
|
_timing((type >> 8) & 0xFF),
|
||||||
|
_started(false),
|
||||||
|
_dirty(true),
|
||||||
|
_raw_format(false),
|
||||||
|
_pixel_count(num_leds),
|
||||||
|
_buf_work(nullptr),
|
||||||
|
_buf_show(nullptr),
|
||||||
|
_pixel_matrix(&TASMOTALED_CHANNEL_ORDERS[0]),
|
||||||
|
_pusher(nullptr)
|
||||||
|
{
|
||||||
|
if (_timing > (TasmotaLed_TimingEnd >> 8)) {
|
||||||
|
_timing = 0;
|
||||||
|
}
|
||||||
|
switch (_type & 0x0F) {
|
||||||
|
// case TasmotaLed_1_W:
|
||||||
|
// _pixel_size = 1;
|
||||||
|
// break;
|
||||||
|
case TasmotaLed_4_WRGB:
|
||||||
|
_pixel_size = 4;
|
||||||
|
break;
|
||||||
|
case TasmotaLed_3_RGB:
|
||||||
|
default: // fallback
|
||||||
|
_pixel_size = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_pixel_matrix = &TASMOTALED_CHANNEL_ORDERS[_pixel_order];
|
||||||
|
|
||||||
|
_buf_work = new uint8_t[_pixel_count * _pixel_size];
|
||||||
|
memset(_buf_work, 0, _pixel_count * _pixel_size);
|
||||||
|
_buf_show = new uint8_t[_pixel_count * _pixel_size];
|
||||||
|
memset(_buf_show, 0, _pixel_count * _pixel_size);
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG, "LED: type=0x%04X pixel_order=0x%02X _timing=%i ", _type, _pixel_order, _timing);
|
||||||
|
}
|
||||||
|
|
||||||
|
TasmotaLED::~TasmotaLED() {
|
||||||
|
if (_pusher) {
|
||||||
|
delete _pusher;
|
||||||
|
_pusher = nullptr;
|
||||||
|
}
|
||||||
|
delete _buf_work;
|
||||||
|
_buf_work = nullptr;
|
||||||
|
delete _buf_show;
|
||||||
|
_buf_show = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Color is passed as 0xWWRRGGBB and copied as WWRRGGBB in _buf_work
|
||||||
|
void TasmotaLED::ClearTo(uint32_t wrgb, int32_t first, int32_t last) {
|
||||||
|
// adjust first and last to be in range of 0 to _pixel_count-1
|
||||||
|
if (first <0) { first += _pixel_count; }
|
||||||
|
if (last <0) { last += _pixel_count; }
|
||||||
|
if (first < 0) { first = 0; }
|
||||||
|
if (last >= _pixel_count) { last = _pixel_count - 1; }
|
||||||
|
if (first > last) { return; }
|
||||||
|
// adjust to pixel format
|
||||||
|
uint8_t b0 = (wrgb >> 24) & 0xFF;
|
||||||
|
uint8_t b1 = (wrgb >> 16) & 0xFF;
|
||||||
|
uint8_t b2 = (wrgb >> 8) & 0xFF;
|
||||||
|
uint8_t b3 = (wrgb ) & 0xFF;
|
||||||
|
|
||||||
|
if ((b0 | b1 | b2 | b3) == 0) {
|
||||||
|
// special version for clearing to black
|
||||||
|
memset(_buf_work + first * _pixel_size, 0, (last - first + 1) * _pixel_size);
|
||||||
|
} else {
|
||||||
|
// fill sub-buffer with RRGGBB or WWRRGGBB (or raw)
|
||||||
|
uint8_t *buf = _buf_work + first * _pixel_size;
|
||||||
|
for (uint32_t i = first; i <= last; i++) {
|
||||||
|
if (_pixel_size == 4) { *buf++ = b0;}
|
||||||
|
*buf++ = b1;
|
||||||
|
*buf++ = b2;
|
||||||
|
*buf++ = b3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TasmotaLED::Show(void) {
|
||||||
|
if (_pusher) {
|
||||||
|
_dirty = false; // we don't use the _dirty attribute and always show
|
||||||
|
|
||||||
|
// copy the input buffer to the work buffer in format to be understood by LED strip
|
||||||
|
if (_raw_format) {
|
||||||
|
memmove(_buf_show, _buf_work, _pixel_count * _pixel_size); // copy buffer in next buffer so we start with the current content
|
||||||
|
} else {
|
||||||
|
uint8_t *buf_from = _buf_work;
|
||||||
|
uint8_t *buf_to = _buf_show;
|
||||||
|
if (_pixel_size == 3) {
|
||||||
|
// copying with swapping 512 pixels (1536 bytes) takes 124 microseconds to copy, so it's negligeable
|
||||||
|
for (uint32_t i = 0; i < _pixel_count; i++) {
|
||||||
|
buf_to[(*_pixel_matrix)[0]] = buf_from[0]; // R
|
||||||
|
buf_to[(*_pixel_matrix)[1]] = buf_from[1]; // G
|
||||||
|
buf_to[(*_pixel_matrix)[2]] = buf_from[2]; // B
|
||||||
|
buf_to += 3;
|
||||||
|
buf_from += 3;
|
||||||
|
}
|
||||||
|
} else if (_pixel_size == 4) {
|
||||||
|
for (uint32_t i = 0; i < _pixel_count; i++) {
|
||||||
|
if (_w_before) { *buf_to++ = buf_from[3]; }
|
||||||
|
buf_to[(*_pixel_matrix)[0]] = buf_from[0]; // R
|
||||||
|
buf_to[(*_pixel_matrix)[1]] = buf_from[1]; // G
|
||||||
|
buf_to[(*_pixel_matrix)[2]] = buf_from[2]; // B
|
||||||
|
if (!_w_before) { *buf_to++ = buf_from[3]; }
|
||||||
|
buf_to += 3; // one increment already happened
|
||||||
|
buf_from += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_pusher->Push(_buf_show); // push to leds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TasmotaLED::SetPixelColor(int32_t index, uint32_t wrgb) {
|
||||||
|
if (index < 0) { index += _pixel_count; }
|
||||||
|
if ((index >= 0) && (index < _pixel_count)) {
|
||||||
|
uint8_t *buf = _buf_work + index * _pixel_size;
|
||||||
|
uint8_t b0 = (wrgb >> 24) & 0xFF;
|
||||||
|
uint8_t b1 = (wrgb >> 16) & 0xFF;
|
||||||
|
uint8_t b2 = (wrgb >> 8) & 0xFF;
|
||||||
|
uint8_t b3 = (wrgb ) & 0xFF;
|
||||||
|
|
||||||
|
if (_pixel_size == 4) { *buf++ = b0;}
|
||||||
|
*buf++ = b1;
|
||||||
|
*buf++ = b2;
|
||||||
|
*buf++ = b3;
|
||||||
|
_dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t TasmotaLED::GetPixelColor(int32_t index) {
|
||||||
|
if (index < 0) { index += _pixel_count; }
|
||||||
|
if ((index >= 0) && (index < _pixel_count)) {
|
||||||
|
uint8_t *buf = _buf_work + index * _pixel_size;
|
||||||
|
uint32_t wrgb = 0;
|
||||||
|
if (_pixel_size == 4) { wrgb = (*buf++) << 24; }
|
||||||
|
wrgb |= (*buf++) << 16;
|
||||||
|
wrgb |= (*buf++) << 8;
|
||||||
|
wrgb |= (*buf++);
|
||||||
|
return wrgb;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TasmotaLED::SetPusher(TasmotaLEDPusher *pusher) {
|
||||||
|
if (_pusher) {
|
||||||
|
delete _pusher;
|
||||||
|
}
|
||||||
|
_pusher = pusher;
|
||||||
|
_started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TasmotaLED::Begin(void) {
|
||||||
|
if (_pusher) {
|
||||||
|
if (_started) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
const TasmotaLED_Timing * timing = &TasmotaLED_Timings[_timing];
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG, "LED: T0H=%i T0L=%i T1H=%i T1L=%i Reset=%i", timing.T0H, timing.T0L, timing.T1H, timing.T1L, timing.Reset);
|
||||||
|
return _pusher->Begin(_pixel_count, _pixel_size, timing);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TasmotaLED::CanShow(void) const {
|
||||||
|
if (_pusher) {
|
||||||
|
return _pusher->CanShow();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ESP32
|
||||||
129
lib/lib_basic/TasmotaLED/src/TasmotaLED.h
Normal file
129
lib/lib_basic/TasmotaLED/src/TasmotaLED.h
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
TasmotaLED.h - Lightweight implementation for adressable leds.
|
||||||
|
|
||||||
|
Copyright (C) 2024 Stephan Hadinger
|
||||||
|
|
||||||
|
This library is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TASMOTALED_H__
|
||||||
|
#define __TASMOTALED_H__
|
||||||
|
|
||||||
|
enum TasmotaLEDTypesEncoding : uint16_t {
|
||||||
|
// bits 0..3 encode for number of bytes per pixel
|
||||||
|
TasmotaLed_1_W = 0x0, // 1 byte per pixel (not used yet)
|
||||||
|
TasmotaLed_3_RGB = 0x1, // 3 bytes per pixel
|
||||||
|
TasmotaLed_4_WRGB = 0x2, // 4 bytes per pixel
|
||||||
|
// bits 4..6 encode for pixel order
|
||||||
|
TasmotaLed_GRB = 0b000 << 4,
|
||||||
|
TasmotaLed_GBR = 0b001 << 4,
|
||||||
|
TasmotaLed_RGB = 0b010 << 4,
|
||||||
|
TasmotaLed_RBG = 0b011 << 4,
|
||||||
|
TasmotaLed_BRG = 0b100 << 4,
|
||||||
|
TasmotaLed_BGR = 0b101 << 4,
|
||||||
|
// bit 7 sets the position for W channel
|
||||||
|
TasmotaLed_xxxW = 0b0 << 7, // W channel after color
|
||||||
|
TasmotaLed_Wxxx = 0b1 << 7, // W channel before color
|
||||||
|
// bits 8..15 encode for timing specifics
|
||||||
|
TasmotaLed_WS2812 = 0 << 8,
|
||||||
|
TasmotaLed_SK6812 = 1 << 8,
|
||||||
|
TasmotaLed_TimingEnd = 2 << 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TasmotaLEDHardware : uint32_t {
|
||||||
|
// low-order bits are reserved for channels numbers and hardware flags - currenlty not useds
|
||||||
|
// bits 16..23
|
||||||
|
TasmotaLed_HW_Default = 0x0 << 16,
|
||||||
|
TasmotaLed_RMT = 1 << 16,
|
||||||
|
TasmotaLed_SPI = 2 << 16,
|
||||||
|
TasmotaLed_I2S = 3 << 16,
|
||||||
|
TasmotaLed_HW_None = 0xFF << 16, // indicates that the specified HW is not supported
|
||||||
|
};
|
||||||
|
|
||||||
|
// Below is the encoding for full strips
|
||||||
|
// We need to keep backwards compatibility so:
|
||||||
|
// 0 = WS2812 (GRB)
|
||||||
|
// 1 = SK6812 with White (GRBW)
|
||||||
|
enum TasmotaLEDTypes : uint16_t {
|
||||||
|
ws2812_grb = TasmotaLed_3_RGB | TasmotaLed_GRB | TasmotaLed_WS2812, // 1 for backwards compatibility
|
||||||
|
sk6812_grbw = TasmotaLed_4_WRGB | TasmotaLed_GRB | TasmotaLed_xxxW | TasmotaLed_SK6812, // 2 for backwards compatibility
|
||||||
|
sk6812_grb = TasmotaLed_3_RGB | TasmotaLed_GRB | TasmotaLed_SK6812,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
/*******************************************************************************************\
|
||||||
|
* class TasmotaLED
|
||||||
|
*
|
||||||
|
* This class is a lightweight replacement for NeoPixelBus library with a smaller
|
||||||
|
* implementation focusing only on pushing a buffer to the leds.
|
||||||
|
*
|
||||||
|
* It supports:
|
||||||
|
* - RMT and I2S hardware support
|
||||||
|
* Possible enhancements could be considered with SPI and Serial
|
||||||
|
* - Led size of 3 bytes (GRB) and 4 bytes (GRBW)
|
||||||
|
* APIs take 0xRRGGBB or 0xRRGGBBWW as input
|
||||||
|
* but Internal buffers use GGRRBB and GGRRBBWW
|
||||||
|
* - Led type of WS2812 and SK6812
|
||||||
|
* - There is no buffer swapping, the working buffer is copied to an internal
|
||||||
|
* buffer just before display, so you can keep a reference to the buffer
|
||||||
|
* and modify it without having to worry about the display
|
||||||
|
* - buffer is cleared at start
|
||||||
|
* - "Dirty" is kept for API compatibility with NeoPixelBus but is glbally ignored
|
||||||
|
* so any call to `Show()` pushes the pixels even if they haven't changed.
|
||||||
|
* Control for dirty pixels should be done by the caller if required.
|
||||||
|
* - We tried to keep as close as possible to NeoPixelBus method names to ease transition
|
||||||
|
\*******************************************************************************************/
|
||||||
|
class TasmotaLEDPusher; // forward definition
|
||||||
|
class TasmotaLED {
|
||||||
|
public:
|
||||||
|
TasmotaLED(uint16_t type, uint16_t num_leds);
|
||||||
|
~TasmotaLED();
|
||||||
|
|
||||||
|
bool Begin(void);
|
||||||
|
void SetPusher(TasmotaLEDPusher *pusher); // needs to be called before `Begin()`, sets the hardware implementation
|
||||||
|
void Show(void); // pushes the pixels to the LED strip
|
||||||
|
inline void SetRawFormat(bool raw_format) { _raw_format = raw_format; }
|
||||||
|
|
||||||
|
void ClearTo(uint32_t rgbw, int32_t first = 0, int32_t last = -1);
|
||||||
|
void SetPixelColor(int32_t index, uint32_t wrgb);
|
||||||
|
uint32_t GetPixelColor(int32_t index);
|
||||||
|
|
||||||
|
uint8_t GetType(void) const { return _type; }
|
||||||
|
uint16_t PixelCount(void) const { return _pixel_count; }
|
||||||
|
uint8_t PixelSize(void) const { return _pixel_size; }
|
||||||
|
inline uint8_t * Pixels(void) const { return _buf_work; }
|
||||||
|
inline bool IsDirty(void) const { return _dirty; }
|
||||||
|
inline void Dirty(void) { _dirty = true; }
|
||||||
|
|
||||||
|
bool CanShow(void) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint16_t _type; // the composite type
|
||||||
|
uint8_t _pixel_order; // permutation between RGB and position of W
|
||||||
|
bool _w_before; // true if W channel comes first (4 channels only)
|
||||||
|
uint8_t _timing; // timing code for strip, 0=WS2812, 1=SK6812...
|
||||||
|
bool _started; // true if the hardware implementation is configured
|
||||||
|
bool _dirty; // for NeoPixelBus compatibility, but ignored by `Push()`
|
||||||
|
bool _raw_format; // if true, copy raw to leds, if false, convert from RGB to GRB or LED format
|
||||||
|
uint16_t _pixel_count; // how many pixels in the strip
|
||||||
|
uint8_t _pixel_size; // how many bytes per pixels, only 3 and 4 are supported
|
||||||
|
uint8_t *_buf_work; // buffer used to draw into, can be modified directly by the caller
|
||||||
|
uint8_t *_buf_show; // copy of the buffer used to push to leds, private to this class
|
||||||
|
const uint8_t (*_pixel_matrix)[3]; // pointer to the pixer_order_matrix
|
||||||
|
TasmotaLEDPusher *_pusher; // pixels pusher implementation based on hardware (RMT, I2S...)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
#endif // __TASMOTALED_H__
|
||||||
97
lib/lib_basic/TasmotaLED/src/TasmotaLEDPusher.cpp
Normal file
97
lib/lib_basic/TasmotaLED/src/TasmotaLEDPusher.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
TasmotaLEDPusher.cpp - Implementation to push Leds via hardware acceleration
|
||||||
|
|
||||||
|
Copyright (C) 2024 Stephan Hadinger
|
||||||
|
|
||||||
|
This library is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
|
||||||
|
#include "TasmotaLEDPusher.h"
|
||||||
|
#include "TasmotaLED.h"
|
||||||
|
|
||||||
|
//**************************************************************************************************************
|
||||||
|
// enable AddLog support within a C++ library
|
||||||
|
extern void AddLog(uint32_t loglevel, PGM_P formatP, ...);
|
||||||
|
enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE};
|
||||||
|
//**************************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
// convert to the appropriate hardware acceleration based on capacities of the SOC
|
||||||
|
uint32_t TasmotaLEDPusher::ResolveHardware(uint32_t hw) {
|
||||||
|
uint32_t hw_orig = hw;
|
||||||
|
// Step 1. discard any unsupported hardware, and replace with TasmotaLed_HW_Default
|
||||||
|
uint32_t hw_type = hw & 0xFF0000; // discard bits 0..15
|
||||||
|
#if !TASMOTALED_HARDWARE_RMT
|
||||||
|
if (hw_type == TasmotaLed_RMT) {
|
||||||
|
hw = TasmotaLed_HW_None;
|
||||||
|
}
|
||||||
|
#endif // TASMOTALED_HARDWARE_RMT
|
||||||
|
#if !TASMOTALED_HARDWARE_SPI
|
||||||
|
if (hw_type == TasmotaLed_SPI) {
|
||||||
|
hw = TasmotaLed_HW_None;
|
||||||
|
}
|
||||||
|
#endif // TASMOTALED_HARDWARE_SPI
|
||||||
|
#if !TASMOTALED_HARDWARE_I2S
|
||||||
|
if (hw_type == TasmotaLed_I2S) {
|
||||||
|
hw = TasmotaLed_HW_None;
|
||||||
|
}
|
||||||
|
#endif // TASMOTALED_HARDWARE_I2S
|
||||||
|
|
||||||
|
// Step 2. If TasmotaLed_HW_Default, find a suitable scheme, RMT preferred
|
||||||
|
#if TASMOTALED_HARDWARE_RMT
|
||||||
|
if ((hw & 0xFF0000) == TasmotaLed_HW_Default) {
|
||||||
|
hw = TasmotaLed_RMT;
|
||||||
|
}
|
||||||
|
#endif // TASMOTALED_HARDWARE_RMT
|
||||||
|
#if TASMOTALED_HARDWARE_I2S
|
||||||
|
if ((hw & 0xFF0000) == TasmotaLed_HW_Default) {
|
||||||
|
hw = TasmotaLed_I2S;
|
||||||
|
}
|
||||||
|
#endif // TASMOTALED_HARDWARE_I2S
|
||||||
|
#if TASMOTALED_HARDWARE_SPI
|
||||||
|
if ((hw & 0xFF0000) == TasmotaLed_HW_Default) {
|
||||||
|
hw = TasmotaLed_SPI;
|
||||||
|
}
|
||||||
|
#endif // TASMOTALED_HARDWARE_SPI
|
||||||
|
return hw;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TasmotaLEDPusher * TasmotaLEDPusher::Create(uint32_t hw, int8_t gpio) {
|
||||||
|
TasmotaLEDPusher * pusher = nullptr;
|
||||||
|
|
||||||
|
hw = TasmotaLEDPusher::ResolveHardware(hw);
|
||||||
|
|
||||||
|
switch (hw & 0XFF0000) {
|
||||||
|
#if TASMOTALED_HARDWARE_RMT
|
||||||
|
case TasmotaLed_RMT:
|
||||||
|
pusher = new TasmotaLEDPusherRMT(gpio);
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, "LED: RMT gpio %i", gpio);
|
||||||
|
break;
|
||||||
|
#endif // TASMOTALED_HARDWARE_RMT
|
||||||
|
#if TASMOTALED_HARDWARE_SPI
|
||||||
|
case TasmotaLed_SPI:
|
||||||
|
pusher = new TasmotaLEDPusherSPI(gpio);
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, "LED: SPI gpio %i", gpio);
|
||||||
|
break;
|
||||||
|
#endif // TASMOTALED_HARDWARE_SPI
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return pusher;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ESP32
|
||||||
161
lib/lib_basic/TasmotaLED/src/TasmotaLEDPusher.h
Normal file
161
lib/lib_basic/TasmotaLED/src/TasmotaLEDPusher.h
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
TasmotaLEDPusher.h - Abstract class for Leds pusher (RMT, SPI, I2S...)
|
||||||
|
|
||||||
|
Copyright (C) 2024 Stephan Hadinger
|
||||||
|
|
||||||
|
This library is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TASMOTALEDPUSHER_H__
|
||||||
|
#define __TASMOTALEDPUSHER_H__
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
// Below are flags to enable of disable each hardware support: RMT, I2S, SPI
|
||||||
|
// By default, only enable RMT support, and SPI is used as fallback if no protocol works
|
||||||
|
//
|
||||||
|
// Use de defines below:
|
||||||
|
// #define TASMOTALED_HARDWARE_RMT 0/1
|
||||||
|
// #define TASMOTALED_HARDWARE_I2S 0/1
|
||||||
|
// #define TASMOTALED_HARDWARE_SPI 0/1
|
||||||
|
//
|
||||||
|
#ifndef TASMOTALED_HARDWARE_RMT
|
||||||
|
#define TASMOTALED_HARDWARE_RMT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TASMOTALED_HARDWARE_I2S
|
||||||
|
#define TASMOTALED_HARDWARE_I2S 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TASMOTALED_HARDWARE_SPI
|
||||||
|
#define TASMOTALED_HARDWARE_SPI 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Disable any hardware if not supported by the SOC
|
||||||
|
#if TASMOTALED_HARDWARE_RMT && !defined(SOC_RMT_SUPPORTED)
|
||||||
|
#undef TASMOTALED_HARDWARE_RMT
|
||||||
|
#define TASMOTALED_HARDWARE_RMT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TASMOTALED_HARDWARE_I2S && !defined(SOC_I2S_SUPPORTED)
|
||||||
|
#undef TASMOTALED_HARDWARE_I2S
|
||||||
|
#define TASMOTALED_HARDWARE_I2S 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TASMOTALED_HARDWARE_SPI && !defined(SOC_GPSPI_SUPPORTED)
|
||||||
|
#undef TASMOTALED_HARDWARE_SPI
|
||||||
|
#define TASMOTALED_HARDWARE_SPI 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// if no protocol is defined, use SPI as fallback
|
||||||
|
#if !TASMOTALED_HARDWARE_RMT && !TASMOTALED_HARDWARE_I2S && !TASMOTALED_HARDWARE_SPI
|
||||||
|
#undef TASMOTALED_HARDWARE_SPI
|
||||||
|
#define TASMOTALED_HARDWARE_SPI 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Timing structure for LEDS - in nanoseconds
|
||||||
|
// It is passed by TasmotaLed to the pushers
|
||||||
|
typedef struct TasmotaLED_Timing {
|
||||||
|
uint16_t T0H, T0L, T1H, T1L;
|
||||||
|
uint32_t Reset;
|
||||||
|
} TasmotaLED_Timing;
|
||||||
|
|
||||||
|
/*******************************************************************************************\
|
||||||
|
* class TasmotaLEDPusher
|
||||||
|
*
|
||||||
|
* This is an virtual abstract class for Leds pusher (RMT, SPI, I2S...)
|
||||||
|
*
|
||||||
|
* Below are interfaces for current implementations
|
||||||
|
\*******************************************************************************************/
|
||||||
|
class TasmotaLEDPusher {
|
||||||
|
public:
|
||||||
|
TasmotaLEDPusher() : _pixel_count(0), _pixel_size(0), _led_timing(nullptr) {};
|
||||||
|
virtual ~TasmotaLEDPusher() {};
|
||||||
|
|
||||||
|
virtual bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) {
|
||||||
|
_pixel_count = pixel_count;
|
||||||
|
_pixel_size = pixel_size;
|
||||||
|
_led_timing = led_timing;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual bool Push(uint8_t *buf) = 0;
|
||||||
|
virtual bool CanShow(void) = 0;
|
||||||
|
|
||||||
|
static uint32_t ResolveHardware(uint32_t hw); // convert to the appropriate hardware acceleration based on capacities of the SOC
|
||||||
|
static TasmotaLEDPusher * Create(uint32_t hw, int8_t gpio); // create instance for the provided type, or nullptr if failed
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint16_t _pixel_count;
|
||||||
|
uint16_t _pixel_size;
|
||||||
|
const TasmotaLED_Timing * _led_timing;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************************************************************************\
|
||||||
|
* class TasmotaLEDPusherRMT
|
||||||
|
*
|
||||||
|
* Implementation based on RMT driver
|
||||||
|
\*******************************************************************************************/
|
||||||
|
#if TASMOTALED_HARDWARE_RMT
|
||||||
|
#include "driver/rmt_tx.h"
|
||||||
|
class TasmotaLEDPusherRMT : public TasmotaLEDPusher {
|
||||||
|
public:
|
||||||
|
TasmotaLEDPusherRMT(int8_t pin) : _pin(pin) {};
|
||||||
|
~TasmotaLEDPusherRMT();
|
||||||
|
|
||||||
|
bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override;
|
||||||
|
|
||||||
|
bool Push(uint8_t *buf) override;
|
||||||
|
bool CanShow(void) override;
|
||||||
|
protected:
|
||||||
|
int8_t _pin;
|
||||||
|
rmt_transmit_config_t _tx_config = {};
|
||||||
|
rmt_channel_handle_t _channel = nullptr;;
|
||||||
|
rmt_encoder_handle_t _led_encoder = nullptr;
|
||||||
|
};
|
||||||
|
#endif // TASMOTALED_HARDWARE_RMT
|
||||||
|
|
||||||
|
/*******************************************************************************************\
|
||||||
|
* class TasmotaLEDPusherSPI
|
||||||
|
*
|
||||||
|
* Implementation based on SPI driver, mandatory for C2
|
||||||
|
\*******************************************************************************************/
|
||||||
|
#if TASMOTALED_HARDWARE_SPI
|
||||||
|
#include <driver/spi_master.h>
|
||||||
|
|
||||||
|
typedef struct led_strip_spi_obj_t {
|
||||||
|
uint8_t * pixel_buf;
|
||||||
|
uint16_t strip_len;
|
||||||
|
uint8_t bytes_per_pixel;
|
||||||
|
spi_host_device_t spi_host;
|
||||||
|
spi_device_handle_t spi_device;
|
||||||
|
spi_transaction_t tx_conf; // transaction in process if any
|
||||||
|
} led_strip_spi_obj;
|
||||||
|
|
||||||
|
class TasmotaLEDPusherSPI : public TasmotaLEDPusher {
|
||||||
|
public:
|
||||||
|
TasmotaLEDPusherSPI(int8_t pin) : _pin(pin), _spi_strip({}) {};
|
||||||
|
~TasmotaLEDPusherSPI();
|
||||||
|
|
||||||
|
bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override;
|
||||||
|
|
||||||
|
bool Push(uint8_t *buf) override;
|
||||||
|
bool CanShow(void) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int8_t _pin;
|
||||||
|
struct led_strip_spi_obj_t _spi_strip;
|
||||||
|
};
|
||||||
|
#endif // TASMOTALED_HARDWARE_SPI
|
||||||
|
|
||||||
|
#endif // __TASMOTALEDPUSHER_H__
|
||||||
240
lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherRMT.cpp
Normal file
240
lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherRMT.cpp
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
TasmotaLEDPusherRMT.cpp - Implementation to push Leds via RMT channel
|
||||||
|
|
||||||
|
Copyright (C) 2024 Stephan Hadinger
|
||||||
|
|
||||||
|
This library is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
|
||||||
|
#include "TasmotaLEDPusher.h"
|
||||||
|
#include "TasmotaLED.h"
|
||||||
|
|
||||||
|
#if TASMOTALED_HARDWARE_RMT
|
||||||
|
#include <rom/gpio.h>
|
||||||
|
#include <esp_check.h>
|
||||||
|
|
||||||
|
//**************************************************************************************************************
|
||||||
|
// enable AddLog support within a C++ library
|
||||||
|
extern void AddLog(uint32_t loglevel, PGM_P formatP, ...);
|
||||||
|
enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE};
|
||||||
|
//**************************************************************************************************************
|
||||||
|
|
||||||
|
/*******************************************************************************************\
|
||||||
|
* Implementation for TasmotaLEDPusherRMT
|
||||||
|
*
|
||||||
|
* Code mostly copied from Tasmota patch to NeoPixelBus applied to support esp-idf 5.x
|
||||||
|
* itself inspired from esp-idf example for RMT encoder from
|
||||||
|
* https://github.com/espressif/esp-idf/tree/v5.3.1/examples/peripherals/rmt/ir_nec_transceiver
|
||||||
|
\*******************************************************************************************/
|
||||||
|
#define RMT_LED_STRIP_RESOLUTION_HZ 40000000 // 40MHz resolution, steps of 25 nanoseconds
|
||||||
|
|
||||||
|
// structure used to pass arguments to `rmt_new_led_strip_encoder`
|
||||||
|
// currently only the encoder resolution in Hz
|
||||||
|
typedef struct {
|
||||||
|
uint32_t resolution; /*!< Encoder resolution, in Hz */
|
||||||
|
} led_strip_encoder_config_t;
|
||||||
|
|
||||||
|
// structure used to store all the necessary information for the RMT encoder
|
||||||
|
typedef struct {
|
||||||
|
rmt_encoder_t base;
|
||||||
|
rmt_encoder_t *bytes_encoder;
|
||||||
|
rmt_encoder_t *copy_encoder;
|
||||||
|
int32_t state;
|
||||||
|
rmt_symbol_word_t reset_code;
|
||||||
|
} rmt_led_strip_encoder_t;
|
||||||
|
|
||||||
|
static IRAM_ATTR size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
|
||||||
|
{
|
||||||
|
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
|
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
|
||||||
|
rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder;
|
||||||
|
rmt_encode_state_t session_state = RMT_ENCODING_RESET;
|
||||||
|
rmt_encode_state_t state = RMT_ENCODING_RESET;
|
||||||
|
size_t encoded_symbols = 0;
|
||||||
|
switch (led_encoder->state) {
|
||||||
|
case 0: // send RGB data
|
||||||
|
encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state);
|
||||||
|
if (session_state & RMT_ENCODING_COMPLETE) {
|
||||||
|
led_encoder->state = 1; // switch to next state when current encoding session finished
|
||||||
|
}
|
||||||
|
if (session_state & RMT_ENCODING_MEM_FULL) {
|
||||||
|
state = static_cast<rmt_encode_state_t>(static_cast<uint8_t>(state) | static_cast<uint8_t>(RMT_ENCODING_MEM_FULL));
|
||||||
|
goto out; // yield if there's no free space for encoding artifacts
|
||||||
|
}
|
||||||
|
// fall-through
|
||||||
|
case 1: // send reset code
|
||||||
|
encoded_symbols += copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code, sizeof(led_encoder->reset_code), &session_state);
|
||||||
|
if (session_state & RMT_ENCODING_COMPLETE) {
|
||||||
|
led_encoder->state = RMT_ENCODING_RESET; // back to the initial encoding session
|
||||||
|
state = static_cast<rmt_encode_state_t>(static_cast<uint8_t>(state) | static_cast<uint8_t>(RMT_ENCODING_COMPLETE));
|
||||||
|
}
|
||||||
|
if (session_state & RMT_ENCODING_MEM_FULL) {
|
||||||
|
state = static_cast<rmt_encode_state_t>(static_cast<uint8_t>(state) | static_cast<uint8_t>(RMT_ENCODING_MEM_FULL));
|
||||||
|
goto out; // yield if there's no free space for encoding artifacts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
*ret_state = state;
|
||||||
|
return encoded_symbols;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder) {
|
||||||
|
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
|
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||||
|
rmt_del_encoder(led_encoder->copy_encoder);
|
||||||
|
delete led_encoder;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder) {
|
||||||
|
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
|
rmt_encoder_reset(led_encoder->bytes_encoder);
|
||||||
|
rmt_encoder_reset(led_encoder->copy_encoder);
|
||||||
|
led_encoder->state = RMT_ENCODING_RESET;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder, rmt_symbol_word_t bit0, rmt_symbol_word_t bit1, rmt_symbol_word_t reset_code) {
|
||||||
|
static const char* TAG = "TASMOTA_RMT";
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
rmt_led_strip_encoder_t *led_encoder = NULL;
|
||||||
|
rmt_bytes_encoder_config_t bytes_encoder_config;
|
||||||
|
rmt_copy_encoder_config_t copy_encoder_config = {};
|
||||||
|
|
||||||
|
ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||||
|
led_encoder = new rmt_led_strip_encoder_t();
|
||||||
|
ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder");
|
||||||
|
led_encoder->base.encode = rmt_encode_led_strip;
|
||||||
|
led_encoder->base.del = rmt_del_led_strip_encoder;
|
||||||
|
led_encoder->base.reset = rmt_led_strip_encoder_reset;
|
||||||
|
led_encoder->reset_code = reset_code;
|
||||||
|
|
||||||
|
bytes_encoder_config.bit0 = bit0;
|
||||||
|
bytes_encoder_config.bit1 = bit1;
|
||||||
|
bytes_encoder_config.flags.msb_first = 1; // WS2812 transfer bit order: G7...G0R7...R0B7...B0 - TODO: more checks
|
||||||
|
|
||||||
|
ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder), err, TAG, "create bytes encoder failed");
|
||||||
|
ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &led_encoder->copy_encoder), err, TAG, "create copy encoder failed");
|
||||||
|
|
||||||
|
*ret_encoder = &led_encoder->base;
|
||||||
|
return ret;
|
||||||
|
err:
|
||||||
|
AddLog(LOG_LEVEL_INFO, "RMT: could not init led encoder");
|
||||||
|
if (led_encoder) {
|
||||||
|
if (led_encoder->bytes_encoder) { rmt_del_encoder(led_encoder->bytes_encoder); }
|
||||||
|
if (led_encoder->copy_encoder) { rmt_del_encoder(led_encoder->copy_encoder); }
|
||||||
|
delete led_encoder;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
TasmotaLEDPusherRMT::~TasmotaLEDPusherRMT() {
|
||||||
|
if (_channel) {
|
||||||
|
rmt_tx_wait_all_done(_channel, 10000 / portTICK_PERIOD_MS);
|
||||||
|
rmt_del_channel(_channel);
|
||||||
|
_channel = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pin >= 0) {
|
||||||
|
gpio_matrix_out(_pin, 0x100, false, false);
|
||||||
|
pinMode(_pin, INPUT);
|
||||||
|
_pin = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TasmotaLEDPusherRMT::Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) {
|
||||||
|
TasmotaLEDPusher::Begin(pixel_count, pixel_size, led_timing);
|
||||||
|
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
rmt_tx_channel_config_t config = {};
|
||||||
|
config.clk_src = RMT_CLK_SRC_DEFAULT;
|
||||||
|
config.gpio_num = static_cast<gpio_num_t>(_pin);
|
||||||
|
config.mem_block_symbols = 192; // memory block size, 64 * 4 = 256 Bytes
|
||||||
|
config.resolution_hz = RMT_LED_STRIP_RESOLUTION_HZ; // 40 MHz tick resolution, i.e., 1 tick = 0.025 µs or 25 ns
|
||||||
|
config.trans_queue_depth = 4; // set the number of transactions that can pend in the background
|
||||||
|
config.flags.invert_out = false; // do not invert output signal
|
||||||
|
config.flags.with_dma = false; // do not need DMA backend
|
||||||
|
|
||||||
|
ret = rmt_new_tx_channel(&config, &_channel);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, "RMT: cannot initialize Gpio %i err=%i", _pin, ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
led_strip_encoder_config_t encoder_config = {
|
||||||
|
.resolution = RMT_LED_STRIP_RESOLUTION_HZ,
|
||||||
|
};
|
||||||
|
|
||||||
|
_tx_config.loop_count = 0; // no loop
|
||||||
|
|
||||||
|
rmt_symbol_word_t RmtBit0 = {
|
||||||
|
.duration0 = (uint16_t) (led_timing->T0H * (RMT_LED_STRIP_RESOLUTION_HZ / 1000000) / 1000),
|
||||||
|
.level0 = 1,
|
||||||
|
.duration1 = (uint16_t) (led_timing->T0L * (RMT_LED_STRIP_RESOLUTION_HZ / 1000000) / 1000),
|
||||||
|
.level1 = 0,
|
||||||
|
};
|
||||||
|
rmt_symbol_word_t RmtBit1 = {
|
||||||
|
.duration0 = (uint16_t) (led_timing->T1H * (RMT_LED_STRIP_RESOLUTION_HZ / 1000000) / 1000),
|
||||||
|
.level0 = 1,
|
||||||
|
.duration1 = (uint16_t) (led_timing->T1L * (RMT_LED_STRIP_RESOLUTION_HZ / 1000000) / 1000),
|
||||||
|
.level1 = 0,
|
||||||
|
};
|
||||||
|
rmt_symbol_word_t RmtReset = {
|
||||||
|
.duration0 = (uint16_t) (led_timing->Reset * (RMT_LED_STRIP_RESOLUTION_HZ / 1000000) / 1000),
|
||||||
|
.level0 = 0,
|
||||||
|
.duration1 = 50 * (RMT_LED_STRIP_RESOLUTION_HZ / 1000000) / 1000,
|
||||||
|
.level1 = 1,
|
||||||
|
};
|
||||||
|
// AddLog(LOG_LEVEL_INFO, "RMT: RmtBit0 0x%08X RmtBit1 0x%08X RmtReset 0x%08X", RmtBit0.val, RmtBit1.val, RmtReset.val);
|
||||||
|
ret = rmt_new_led_strip_encoder(&encoder_config, &_led_encoder, RmtBit0, RmtBit1, RmtReset);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
// AddLog(LOG_LEVEL_INFO, "RMT: cannot initialize led strip encoder err=%i", ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ret = rmt_enable(_channel);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
// AddLog(LOG_LEVEL_INFO, "RMT: cannot enable channel err=%i", ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TasmotaLEDPusherRMT::CanShow(void) {
|
||||||
|
if (_channel) {
|
||||||
|
return (ESP_OK == rmt_tx_wait_all_done(_channel, 0));
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TasmotaLEDPusherRMT::Push(uint8_t *buf) {
|
||||||
|
|
||||||
|
// wait for not actively sending data
|
||||||
|
// this will time out at 1 second, an arbitrarily long period of time
|
||||||
|
// and do nothing if this happens
|
||||||
|
esp_err_t ret = rmt_tx_wait_all_done(_channel, 1000 / portTICK_PERIOD_MS);
|
||||||
|
if (ESP_OK == ret) {
|
||||||
|
// now start the RMT transmit with the editing buffer before we swap
|
||||||
|
ret = rmt_transmit(_channel, _led_encoder, buf, _pixel_count * _pixel_size, &_tx_config);
|
||||||
|
if (ESP_OK != ret) {
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, "RMT: cannot transmit err=%i", ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TASMOTALED_HARDWARE_RMT
|
||||||
|
#endif // ESP32
|
||||||
191
lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherSPI.cpp
Normal file
191
lib/lib_basic/TasmotaLED/src/TasmotaLEDPusherSPI.cpp
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
/*
|
||||||
|
TasmotaLEDPusherRMT.cpp - Implementation to push Leds via SPI channel
|
||||||
|
|
||||||
|
Copyright (C) 2024 Stephan Hadinger
|
||||||
|
|
||||||
|
This library is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
|
||||||
|
#include "TasmotaLEDPusher.h"
|
||||||
|
#include "TasmotaLED.h"
|
||||||
|
|
||||||
|
#if TASMOTALED_HARDWARE_SPI
|
||||||
|
#include <rom/gpio.h>
|
||||||
|
|
||||||
|
//**************************************************************************************************************
|
||||||
|
// enable AddLog support within a C++ library
|
||||||
|
extern void AddLog(uint32_t loglevel, PGM_P formatP, ...);
|
||||||
|
enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE};
|
||||||
|
//**************************************************************************************************************
|
||||||
|
|
||||||
|
/*******************************************************************************************\
|
||||||
|
* Implementation for TasmotaLEDPusherSPI
|
||||||
|
*
|
||||||
|
\*******************************************************************************************/
|
||||||
|
|
||||||
|
#define LED_STRIP_SPI_DEFAULT_RESOLUTION (25 * 100 * 1000) // 2.5MHz resolution
|
||||||
|
#define LED_STRIP_SPI_DEFAULT_TRANS_QUEUE_SIZE 4
|
||||||
|
|
||||||
|
#define SPI_BYTES_PER_COLOR_BYTE 3
|
||||||
|
#define SPI_BITS_PER_COLOR_BYTE (SPI_BYTES_PER_COLOR_BYTE * 8)
|
||||||
|
|
||||||
|
static void __led_strip_spi_bit(uint8_t data, uint8_t *buf)
|
||||||
|
{
|
||||||
|
// Each color of 1 bit is represented by 3 bits of SPI, low_level:100 ,high_level:110
|
||||||
|
// So a color byte occupies 3 bytes of SPI.
|
||||||
|
buf[0] = (data & BIT(5) ? BIT(1) | BIT(0) : BIT(1)) | (data & BIT(6) ? BIT(4) | BIT(3) : BIT(4)) | (data & BIT(7) ? BIT(7) | BIT(6) : BIT(7));
|
||||||
|
buf[1] = (BIT(0)) | (data & BIT(3) ? BIT(3) | BIT(2) : BIT(3)) | (data & BIT(4) ? BIT(6) | BIT(5) : BIT(6));
|
||||||
|
buf[2] = (data & BIT(0) ? BIT(2) | BIT(1) : BIT(2)) | (data & BIT(1) ? BIT(5) | BIT(4) : BIT(5)) | (data & BIT(2) ? BIT(7) : 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t led_strip_spi_refresh(led_strip_spi_obj * spi_strip)
|
||||||
|
{
|
||||||
|
spi_strip->tx_conf.length = spi_strip->strip_len * spi_strip->bytes_per_pixel * SPI_BITS_PER_COLOR_BYTE;
|
||||||
|
spi_strip->tx_conf.tx_buffer = spi_strip->pixel_buf;
|
||||||
|
spi_strip->tx_conf.rx_buffer = NULL;
|
||||||
|
spi_device_transmit(spi_strip->spi_device, &spi_strip->tx_conf);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_strip_transmit_buffer(led_strip_spi_obj * spi_strip, uint8_t * buffer_rgbw) {
|
||||||
|
// Timing for 512 pixels (extreme test)
|
||||||
|
// Copying to buffer: 418 us
|
||||||
|
// sending pixels: 16.2 ms
|
||||||
|
uint8_t * buf = buffer_rgbw;
|
||||||
|
uint8_t * pix_buf = spi_strip->pixel_buf;
|
||||||
|
for (int i = 0; i < spi_strip->strip_len; i++) {
|
||||||
|
// LED_PIXEL_FORMAT_GRB takes 72bits(9bytes)
|
||||||
|
__led_strip_spi_bit(*buf++, pix_buf); pix_buf += SPI_BYTES_PER_COLOR_BYTE;
|
||||||
|
__led_strip_spi_bit(*buf++, pix_buf); pix_buf += SPI_BYTES_PER_COLOR_BYTE;
|
||||||
|
__led_strip_spi_bit(*buf++, pix_buf); pix_buf += SPI_BYTES_PER_COLOR_BYTE;
|
||||||
|
if (spi_strip->bytes_per_pixel > 3) {
|
||||||
|
__led_strip_spi_bit(*buf++, pix_buf); pix_buf += SPI_BYTES_PER_COLOR_BYTE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Refresh the strip to send data */
|
||||||
|
led_strip_spi_refresh(spi_strip);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TasmotaLEDPusherSPI::~TasmotaLEDPusherSPI() {
|
||||||
|
if (_spi_strip.spi_device) {
|
||||||
|
spi_bus_remove_device(_spi_strip.spi_device);
|
||||||
|
}
|
||||||
|
if (_spi_strip.spi_host) {
|
||||||
|
spi_bus_free(_spi_strip.spi_host);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pin >= 0) {
|
||||||
|
gpio_matrix_out(_pin, 0x100, false, false);
|
||||||
|
pinMode(_pin, INPUT);
|
||||||
|
_pin = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TasmotaLEDPusherSPI::Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) {
|
||||||
|
TasmotaLEDPusher::Begin(pixel_count, pixel_size, led_timing);
|
||||||
|
_spi_strip.bytes_per_pixel = _pixel_size;
|
||||||
|
_spi_strip.strip_len = _pixel_count;
|
||||||
|
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
uint32_t mem_caps = MALLOC_CAP_DEFAULT;
|
||||||
|
// spi_clock_source_t clk_src = SPI_CLK_SRC_DEFAULT;
|
||||||
|
spi_bus_config_t spi_bus_cfg;
|
||||||
|
spi_device_interface_config_t spi_dev_cfg;
|
||||||
|
spi_host_device_t spi_host = SPI2_HOST;
|
||||||
|
bool with_dma = true; /// TODO: pass value or compute based on pixelcount
|
||||||
|
int clock_resolution_khz = 0;
|
||||||
|
|
||||||
|
if (with_dma) { // TODO
|
||||||
|
// DMA buffer must be placed in internal SRAM
|
||||||
|
mem_caps |= MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA;
|
||||||
|
}
|
||||||
|
_spi_strip.pixel_buf = (uint8_t *)heap_caps_calloc(1, _pixel_count * _pixel_size * SPI_BYTES_PER_COLOR_BYTE, mem_caps);
|
||||||
|
if (_spi_strip.pixel_buf == nullptr) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("LED: Error no mem for spi strip"));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_bus_cfg = {
|
||||||
|
.mosi_io_num = _pin,
|
||||||
|
//Only use MOSI to generate the signal, set -1 when other pins are not used.
|
||||||
|
.miso_io_num = -1,
|
||||||
|
.sclk_io_num = -1,
|
||||||
|
.quadwp_io_num = -1,
|
||||||
|
.quadhd_io_num = -1,
|
||||||
|
.max_transfer_sz = _pixel_count * _pixel_size * SPI_BYTES_PER_COLOR_BYTE,
|
||||||
|
};
|
||||||
|
err = spi_bus_initialize(spi_host, &spi_bus_cfg, with_dma ? SPI_DMA_CH_AUTO : SPI_DMA_DISABLED);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("LED: Error create SPI bus failed"));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
_spi_strip.spi_host = spi_host; // confirmed working, so keep it's value to free it later
|
||||||
|
|
||||||
|
spi_dev_cfg = {
|
||||||
|
.command_bits = 0,
|
||||||
|
.address_bits = 0,
|
||||||
|
.dummy_bits = 0,
|
||||||
|
.mode = 0,
|
||||||
|
//set -1 when CS is not used
|
||||||
|
.clock_source = SPI_CLK_SRC_DEFAULT, // clk_src,
|
||||||
|
.clock_speed_hz = LED_STRIP_SPI_DEFAULT_RESOLUTION,
|
||||||
|
.spics_io_num = -1,
|
||||||
|
.queue_size = LED_STRIP_SPI_DEFAULT_TRANS_QUEUE_SIZE,
|
||||||
|
};
|
||||||
|
err = spi_bus_add_device(_spi_strip.spi_host, &spi_dev_cfg, &_spi_strip.spi_device);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
// AddLog(LOG_LEVEL_INFO, "LED: Error failed to add spi device");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_device_get_actual_freq(_spi_strip.spi_device, &clock_resolution_khz);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
// AddLog(LOG_LEVEL_INFO, "LED: Error failed to get spi frequency");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
// TODO: ideally we should decide the SPI_BYTES_PER_COLOR_BYTE by the real clock resolution
|
||||||
|
// But now, let's fixed the resolution, the downside is, we don't support a clock source whose frequency is not multiple of LED_STRIP_SPI_DEFAULT_RESOLUTION
|
||||||
|
if (clock_resolution_khz != LED_STRIP_SPI_DEFAULT_RESOLUTION / 1000) {
|
||||||
|
// AddLog(LOG_LEVEL_INFO, "LED: Error unsupported clock resolution: %dKHz", clock_resolution_khz);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
err:
|
||||||
|
if (_spi_strip.spi_device) {
|
||||||
|
spi_bus_remove_device(_spi_strip.spi_device);
|
||||||
|
}
|
||||||
|
if (_spi_strip.spi_host) {
|
||||||
|
spi_bus_free(_spi_strip.spi_host);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TasmotaLEDPusherSPI::CanShow(void) {
|
||||||
|
return true; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TasmotaLEDPusherSPI::Push(uint8_t *buf) {
|
||||||
|
|
||||||
|
if (CanShow()) {
|
||||||
|
led_strip_transmit_buffer(&_spi_strip, buf);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TASMOTALED_HARDWARE_SPI
|
||||||
|
#endif // ESP32
|
||||||
@ -680,14 +680,15 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
|
|||||||
if (*lp == '\n' || *lp == ' ') { // Add space char
|
if (*lp == '\n' || *lp == ' ') { // Add space char
|
||||||
lp++;
|
lp++;
|
||||||
} else {
|
} else {
|
||||||
lp = strchr(lp, '\n');
|
char *lp1;
|
||||||
if (!lp) {
|
lp1 = strchr(lp, '\n');
|
||||||
lp = strchr(lp, ' ');
|
if (!lp1) {
|
||||||
if (!lp) {
|
lp1 = strchr(lp, ' ');
|
||||||
|
if (!lp1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lp++;
|
lp = lp1 + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -558,6 +558,8 @@ void ESPKNXIP::__loop_knx()
|
|||||||
|
|
||||||
DEBUG_PRINTLN(F(""));
|
DEBUG_PRINTLN(F(""));
|
||||||
|
|
||||||
|
udp.flush();
|
||||||
|
|
||||||
knx_ip_pkt_t *knx_pkt = (knx_ip_pkt_t *)buf;
|
knx_ip_pkt_t *knx_pkt = (knx_ip_pkt_t *)buf;
|
||||||
|
|
||||||
DEBUG_PRINT(F("ST: 0x"));
|
DEBUG_PRINT(F("ST: 0x"));
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@file Adafruit_TSL2591.h
|
@file Adafruit_TSL2591.h
|
||||||
@author KT0WN (adafruit.com)
|
@author KT0WN (adafruit.com)
|
||||||
|
|
||||||
This is a library for the Adafruit TSL2591 breakout board
|
This is a library for the Adafruit TSL2591 breakout board
|
||||||
|
|||||||
258
lib/lib_i2c/BlueRobotics_MS5837_Library/MS5837.cpp
Normal file
258
lib/lib_i2c/BlueRobotics_MS5837_Library/MS5837.cpp
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
#include "MS5837.h"
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
const uint8_t MS5837_ADDR = 0x76;
|
||||||
|
const uint8_t MS5837_RESET = 0x1E;
|
||||||
|
const uint8_t MS5837_ADC_READ = 0x00;
|
||||||
|
const uint8_t MS5837_PROM_READ = 0xA0;
|
||||||
|
const uint8_t MS5837_CONVERT_D1_8192 = 0x4A;
|
||||||
|
const uint8_t MS5837_CONVERT_D2_8192 = 0x5A;
|
||||||
|
|
||||||
|
const float MS5837::Pa = 100.0f;
|
||||||
|
const float MS5837::bar = 0.001f;
|
||||||
|
const float MS5837::mbar = 1.0f;
|
||||||
|
|
||||||
|
const uint8_t MS5837::MS5837_30BA = 0;
|
||||||
|
const uint8_t MS5837::MS5837_02BA = 1;
|
||||||
|
const uint8_t MS5837::MS5837_UNRECOGNISED = 255;
|
||||||
|
|
||||||
|
const uint8_t MS5837_02BA01 = 0x00; // Sensor version: From MS5837_02BA datasheet Version PROM Word 0
|
||||||
|
const uint8_t MS5837_02BA21 = 0x15; // Sensor version: From MS5837_02BA datasheet Version PROM Word 0
|
||||||
|
const uint8_t MS5837_30BA26 = 0x1A; // Sensor version: From MS5837_30BA datasheet Version PROM Word 0
|
||||||
|
|
||||||
|
MS5837::MS5837() {
|
||||||
|
fluidDensity = 1029;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MS5837::begin(TwoWire &wirePort) {
|
||||||
|
return (init(wirePort));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MS5837::init(TwoWire &wirePort) {
|
||||||
|
_i2cPort = &wirePort; //Grab which port the user wants us to use
|
||||||
|
|
||||||
|
// Reset the MS5837, per datasheet
|
||||||
|
_i2cPort->beginTransmission(MS5837_ADDR);
|
||||||
|
_i2cPort->write(MS5837_RESET);
|
||||||
|
_i2cPort->endTransmission();
|
||||||
|
|
||||||
|
// Wait for reset to complete
|
||||||
|
delay(10);
|
||||||
|
|
||||||
|
// Read calibration values and CRC
|
||||||
|
for ( uint8_t i = 0 ; i < 7 ; i++ ) {
|
||||||
|
_i2cPort->beginTransmission(MS5837_ADDR);
|
||||||
|
_i2cPort->write(MS5837_PROM_READ+i*2);
|
||||||
|
_i2cPort->endTransmission();
|
||||||
|
|
||||||
|
_i2cPort->requestFrom(MS5837_ADDR, (uint8_t)2);
|
||||||
|
C[i] = (_i2cPort->read() << 8) | _i2cPort->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that data is correct with CRC
|
||||||
|
uint8_t crcRead = C[0] >> 12;
|
||||||
|
uint8_t crcCalculated = crc4(C);
|
||||||
|
|
||||||
|
if ( crcCalculated != crcRead ) {
|
||||||
|
return false; // CRC fail
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t version = (C[0] >> 5) & 0x7F; // Extract the sensor version from PROM Word 0
|
||||||
|
|
||||||
|
// Set _model according to the sensor version
|
||||||
|
if (version == MS5837_02BA01)
|
||||||
|
{
|
||||||
|
_model = MS5837_02BA;
|
||||||
|
}
|
||||||
|
else if (version == MS5837_02BA21)
|
||||||
|
{
|
||||||
|
_model = MS5837_02BA;
|
||||||
|
}
|
||||||
|
else if (version == MS5837_30BA26)
|
||||||
|
{
|
||||||
|
_model = MS5837_30BA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_model = MS5837_UNRECOGNISED;
|
||||||
|
}
|
||||||
|
// The sensor has passed the CRC check, so we should return true even if
|
||||||
|
// the sensor version is unrecognised.
|
||||||
|
// (The MS5637 has the same address as the MS5837 and will also pass the CRC check)
|
||||||
|
// (but will hopefully be unrecognised.)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MS5837::setModel(uint8_t model) {
|
||||||
|
_model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MS5837::getModel() {
|
||||||
|
return (_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MS5837::setFluidDensity(float density) {
|
||||||
|
fluidDensity = density;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MS5837::read() {
|
||||||
|
//Check that _i2cPort is not NULL (i.e. has the user forgoten to call .init or .begin?)
|
||||||
|
if (_i2cPort == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request D1 conversion
|
||||||
|
_i2cPort->beginTransmission(MS5837_ADDR);
|
||||||
|
_i2cPort->write(MS5837_CONVERT_D1_8192);
|
||||||
|
_i2cPort->endTransmission();
|
||||||
|
|
||||||
|
delay(20); // Max conversion time per datasheet
|
||||||
|
|
||||||
|
_i2cPort->beginTransmission(MS5837_ADDR);
|
||||||
|
_i2cPort->write(MS5837_ADC_READ);
|
||||||
|
_i2cPort->endTransmission();
|
||||||
|
|
||||||
|
_i2cPort->requestFrom(MS5837_ADDR, (uint8_t)3);
|
||||||
|
D1_pres = 0;
|
||||||
|
D1_pres = _i2cPort->read();
|
||||||
|
D1_pres = (D1_pres << 8) | _i2cPort->read();
|
||||||
|
D1_pres = (D1_pres << 8) | _i2cPort->read();
|
||||||
|
|
||||||
|
// Request D2 conversion
|
||||||
|
_i2cPort->beginTransmission(MS5837_ADDR);
|
||||||
|
_i2cPort->write(MS5837_CONVERT_D2_8192);
|
||||||
|
_i2cPort->endTransmission();
|
||||||
|
|
||||||
|
delay(20); // Max conversion time per datasheet
|
||||||
|
|
||||||
|
_i2cPort->beginTransmission(MS5837_ADDR);
|
||||||
|
_i2cPort->write(MS5837_ADC_READ);
|
||||||
|
_i2cPort->endTransmission();
|
||||||
|
|
||||||
|
_i2cPort->requestFrom(MS5837_ADDR, (uint8_t)3);
|
||||||
|
D2_temp = 0;
|
||||||
|
D2_temp = _i2cPort->read();
|
||||||
|
D2_temp = (D2_temp << 8) | _i2cPort->read();
|
||||||
|
D2_temp = (D2_temp << 8) | _i2cPort->read();
|
||||||
|
|
||||||
|
calculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MS5837::calculate() {
|
||||||
|
// Given C1-C6 and D1, D2, calculated TEMP and P
|
||||||
|
// Do conversion first and then second order temp compensation
|
||||||
|
|
||||||
|
int32_t dT = 0;
|
||||||
|
int64_t SENS = 0;
|
||||||
|
int64_t OFF = 0;
|
||||||
|
int32_t SENSi = 0;
|
||||||
|
int32_t OFFi = 0;
|
||||||
|
int32_t Ti = 0;
|
||||||
|
int64_t OFF2 = 0;
|
||||||
|
int64_t SENS2 = 0;
|
||||||
|
|
||||||
|
// Terms called
|
||||||
|
dT = D2_temp-uint32_t(C[5])*256l;
|
||||||
|
if ( _model == MS5837_02BA ) {
|
||||||
|
SENS = int64_t(C[1])*65536l+(int64_t(C[3])*dT)/128l;
|
||||||
|
OFF = int64_t(C[2])*131072l+(int64_t(C[4])*dT)/64l;
|
||||||
|
P = (D1_pres*SENS/(2097152l)-OFF)/(32768l);
|
||||||
|
} else {
|
||||||
|
SENS = int64_t(C[1])*32768l+(int64_t(C[3])*dT)/256l;
|
||||||
|
OFF = int64_t(C[2])*65536l+(int64_t(C[4])*dT)/128l;
|
||||||
|
P = (D1_pres*SENS/(2097152l)-OFF)/(8192l);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temp conversion
|
||||||
|
TEMP = 2000l+int64_t(dT)*C[6]/8388608LL;
|
||||||
|
|
||||||
|
//Second order compensation
|
||||||
|
if ( _model == MS5837_02BA ) {
|
||||||
|
if((TEMP/100)<20){ //Low temp
|
||||||
|
Ti = (11*int64_t(dT)*int64_t(dT))/(34359738368LL);
|
||||||
|
OFFi = (31*(TEMP-2000)*(TEMP-2000))/8;
|
||||||
|
SENSi = (63*(TEMP-2000)*(TEMP-2000))/32;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if((TEMP/100)<20){ //Low temp
|
||||||
|
Ti = (3*int64_t(dT)*int64_t(dT))/(8589934592LL);
|
||||||
|
OFFi = (3*(TEMP-2000)*(TEMP-2000))/2;
|
||||||
|
SENSi = (5*(TEMP-2000)*(TEMP-2000))/8;
|
||||||
|
if((TEMP/100)<-15){ //Very low temp
|
||||||
|
OFFi = OFFi+7*(TEMP+1500l)*(TEMP+1500l);
|
||||||
|
SENSi = SENSi+4*(TEMP+1500l)*(TEMP+1500l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if((TEMP/100)>=20){ //High temp
|
||||||
|
Ti = 2*(dT*dT)/(137438953472LL);
|
||||||
|
OFFi = (1*(TEMP-2000)*(TEMP-2000))/16;
|
||||||
|
SENSi = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OFF2 = OFF-OFFi; //Calculate pressure and temp second order
|
||||||
|
SENS2 = SENS-SENSi;
|
||||||
|
|
||||||
|
TEMP = (TEMP-Ti);
|
||||||
|
|
||||||
|
if ( _model == MS5837_02BA ) {
|
||||||
|
P = (((D1_pres*SENS2)/2097152l-OFF2)/32768l);
|
||||||
|
} else {
|
||||||
|
P = (((D1_pres*SENS2)/2097152l-OFF2)/8192l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float MS5837::pressure(float conversion) {
|
||||||
|
if ( _model == MS5837_02BA ) {
|
||||||
|
return P*conversion/100.0f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return P*conversion/10.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float MS5837::temperature() {
|
||||||
|
return TEMP/100.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The pressure sensor measures absolute pressure, so it will measure the atmospheric pressure + water pressure
|
||||||
|
// We subtract the atmospheric pressure to calculate the depth with only the water pressure
|
||||||
|
// The average atmospheric pressure of 101300 pascal is used for the calcuation, but atmospheric pressure varies
|
||||||
|
// If the atmospheric pressure is not 101300 at the time of reading, the depth reported will be offset
|
||||||
|
// In order to calculate the correct depth, the actual atmospheric pressure should be measured once in air, and
|
||||||
|
// that value should subtracted for subsequent depth calculations.
|
||||||
|
float MS5837::depth() {
|
||||||
|
return (pressure(MS5837::Pa)-101300)/(fluidDensity*9.80665f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float MS5837::altitude() {
|
||||||
|
return (1-pow((pressure()/1013.25f),.190284f))*145366.45f*.3048f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t MS5837::crc4(uint16_t n_prom[]) {
|
||||||
|
uint16_t n_rem = 0;
|
||||||
|
|
||||||
|
n_prom[0] = ((n_prom[0]) & 0x0FFF);
|
||||||
|
n_prom[7] = 0;
|
||||||
|
|
||||||
|
for ( uint8_t i = 0 ; i < 16; i++ ) {
|
||||||
|
if ( i%2 == 1 ) {
|
||||||
|
n_rem ^= (uint16_t)((n_prom[i>>1]) & 0x00FF);
|
||||||
|
} else {
|
||||||
|
n_rem ^= (uint16_t)(n_prom[i>>1] >> 8);
|
||||||
|
}
|
||||||
|
for ( uint8_t n_bit = 8 ; n_bit > 0 ; n_bit-- ) {
|
||||||
|
if ( n_rem & 0x8000 ) {
|
||||||
|
n_rem = (n_rem << 1) ^ 0x3000;
|
||||||
|
} else {
|
||||||
|
n_rem = (n_rem << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n_rem = ((n_rem >> 12) & 0x000F);
|
||||||
|
|
||||||
|
return n_rem ^ 0x00;
|
||||||
|
}
|
||||||
113
lib/lib_i2c/BlueRobotics_MS5837_Library/MS5837.h
Normal file
113
lib/lib_i2c/BlueRobotics_MS5837_Library/MS5837.h
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/* Blue Robotics Arduino MS5837-30BA Pressure/Temperature Sensor Library
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
Title: Blue Robotics Arduino MS5837-30BA Pressure/Temperature Sensor Library
|
||||||
|
|
||||||
|
Description: This library provides utilities to communicate with and to
|
||||||
|
read data from the Measurement Specialties MS5837-30BA pressure/temperature
|
||||||
|
sensor.
|
||||||
|
|
||||||
|
Authors: Rustom Jehangir, Blue Robotics Inc.
|
||||||
|
Adam Šimko, Blue Robotics Inc.
|
||||||
|
|
||||||
|
-------------------------------
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Blue Robotics Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
-------------------------------*/
|
||||||
|
|
||||||
|
#ifndef MS5837_H_BLUEROBOTICS
|
||||||
|
#define MS5837_H_BLUEROBOTICS
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
class MS5837 {
|
||||||
|
public:
|
||||||
|
static const float Pa;
|
||||||
|
static const float bar;
|
||||||
|
static const float mbar;
|
||||||
|
|
||||||
|
static const uint8_t MS5837_30BA;
|
||||||
|
static const uint8_t MS5837_02BA;
|
||||||
|
static const uint8_t MS5837_UNRECOGNISED;
|
||||||
|
|
||||||
|
MS5837();
|
||||||
|
|
||||||
|
bool init(TwoWire &wirePort = Wire);
|
||||||
|
bool begin(TwoWire &wirePort = Wire); // Calls init()
|
||||||
|
|
||||||
|
/** Set model of MS5837 sensor. Valid options are MS5837::MS5837_30BA (default)
|
||||||
|
* and MS5837::MS5837_02BA.
|
||||||
|
*/
|
||||||
|
void setModel(uint8_t model);
|
||||||
|
uint8_t getModel();
|
||||||
|
|
||||||
|
/** Provide the density of the working fluid in kg/m^3. Default is for
|
||||||
|
* seawater. Should be 997 for freshwater.
|
||||||
|
*/
|
||||||
|
void setFluidDensity(float density);
|
||||||
|
|
||||||
|
/** The read from I2C takes up to 40 ms, so use sparingly is possible.
|
||||||
|
*/
|
||||||
|
void read();
|
||||||
|
|
||||||
|
/** Pressure returned in mbar or mbar*conversion rate.
|
||||||
|
*/
|
||||||
|
float pressure(float conversion = 1.0f);
|
||||||
|
|
||||||
|
/** Temperature returned in deg C.
|
||||||
|
*/
|
||||||
|
float temperature();
|
||||||
|
|
||||||
|
/** Depth returned in meters (valid for operation in incompressible
|
||||||
|
* liquids only. Uses density that is set for fresh or seawater.
|
||||||
|
*/
|
||||||
|
float depth();
|
||||||
|
|
||||||
|
/** Altitude returned in meters (valid for operation in air only).
|
||||||
|
*/
|
||||||
|
float altitude();
|
||||||
|
|
||||||
|
uint8_t crc4(uint16_t n_prom[]);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//This stores the requested i2c port
|
||||||
|
TwoWire * _i2cPort;
|
||||||
|
|
||||||
|
uint16_t C[8];
|
||||||
|
uint32_t D1_pres, D2_temp;
|
||||||
|
int32_t TEMP;
|
||||||
|
int32_t P;
|
||||||
|
uint8_t _model;
|
||||||
|
|
||||||
|
float fluidDensity;
|
||||||
|
|
||||||
|
/** Performs calculations per the sensor data sheet for conversion and
|
||||||
|
* second order compensation.
|
||||||
|
*/
|
||||||
|
void calculate();
|
||||||
|
|
||||||
|
//uint8_t crc4(uint16_t n_prom[]);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -47,7 +47,9 @@
|
|||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <core_version.h>
|
#if __has_include("core_version.h") // ESP32 Stage has no core_version.h file. Disable include via PlatformIO Option
|
||||||
|
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_7_1)
|
||||||
|
#endif // ESP32_STAGE
|
||||||
#undef DEBUG_TLS
|
#undef DEBUG_TLS
|
||||||
|
|
||||||
#ifdef DEBUG_TLS
|
#ifdef DEBUG_TLS
|
||||||
|
|||||||
@ -20,7 +20,9 @@
|
|||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <core_version.h>
|
#if __has_include("core_version.h") // ESP32 Stage has no core_version.h file. Disable include via PlatformIO Option
|
||||||
|
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_7_1)
|
||||||
|
#endif // ESP32_STAGE
|
||||||
|
|
||||||
#ifndef wificlientlightbearssl_h
|
#ifndef wificlientlightbearssl_h
|
||||||
#define wificlientlightbearssl_h
|
#define wificlientlightbearssl_h
|
||||||
|
|||||||
@ -75,7 +75,7 @@
|
|||||||
|
|
||||||
#if !defined(ESP_MAIL_DISABLE_NATIVE_ETHERNET)
|
#if !defined(ESP_MAIL_DISABLE_NATIVE_ETHERNET)
|
||||||
|
|
||||||
#if defined(ESP32) && __has_include(<esp_eth_driver.h>)
|
#if defined(ESP32) && defined(CONFIG_ETH_ENABLED)
|
||||||
#include <ETH.h>
|
#include <ETH.h>
|
||||||
#define ESP_MAIL_ETH_IS_AVAILABLE
|
#define ESP_MAIL_ETH_IS_AVAILABLE
|
||||||
#elif defined(ESP8266) && defined(ESP8266_CORE_SDK_V3_X_X)
|
#elif defined(ESP8266) && defined(ESP8266_CORE_SDK_V3_X_X)
|
||||||
@ -128,4 +128,4 @@
|
|||||||
#define WiFI_CONNECTED false
|
#define WiFI_CONNECTED false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -152,7 +152,7 @@ BERRY_LOCAL const bntvmodule_t* const be_module_table[] = {
|
|||||||
&be_native_module(unishox),
|
&be_native_module(unishox),
|
||||||
#endif // USE_UNISHOX_COMPRESSION
|
#endif // USE_UNISHOX_COMPRESSION
|
||||||
|
|
||||||
#ifdef USE_WS2812
|
#if defined(USE_WS2812) && !defined(USE_WS2812_FORCE_NEOPIXELBUS)
|
||||||
&be_native_module(animate),
|
&be_native_module(animate),
|
||||||
#endif // USE_WS2812
|
#endif // USE_WS2812
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ BERRY_LOCAL const bntvmodule_t* const be_module_table[] = {
|
|||||||
&be_native_module(partition_core),
|
&be_native_module(partition_core),
|
||||||
&be_native_module(crc),
|
&be_native_module(crc),
|
||||||
&be_native_module(crypto),
|
&be_native_module(crypto),
|
||||||
#if defined(USE_BERRY_ULP) && ((CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3))
|
#if defined(USE_BERRY_ULP) && defined(CONFIG_ULP_COPROC_ENABLED)
|
||||||
&be_native_module(ULP),
|
&be_native_module(ULP),
|
||||||
#endif // USE_BERRY_ULP
|
#endif // USE_BERRY_ULP
|
||||||
#if defined(USE_BERRY_TF_LITE)
|
#if defined(USE_BERRY_TF_LITE)
|
||||||
@ -293,7 +293,7 @@ BERRY_LOCAL bclass_array be_class_table = {
|
|||||||
#ifdef USE_BERRY_TCPSERVER
|
#ifdef USE_BERRY_TCPSERVER
|
||||||
&be_native_class(tcpserver),
|
&be_native_class(tcpserver),
|
||||||
#endif // USE_BERRY_TCPSERVER
|
#endif // USE_BERRY_TCPSERVER
|
||||||
#ifdef USE_WS2812
|
#if defined(USE_WS2812) && !defined(USE_WS2812_FORCE_NEOPIXELBUS)
|
||||||
&be_native_class(Leds_ntv),
|
&be_native_class(Leds_ntv),
|
||||||
&be_native_class(Leds),
|
&be_native_class(Leds),
|
||||||
#endif // USE_WS2812
|
#endif // USE_WS2812
|
||||||
|
|||||||
@ -45,10 +45,10 @@ extern "C" {
|
|||||||
uint32_t g2 = (color_b >> 8) & 0xFF;
|
uint32_t g2 = (color_b >> 8) & 0xFF;
|
||||||
uint32_t b2 = (color_b ) & 0xFF;
|
uint32_t b2 = (color_b ) & 0xFF;
|
||||||
uint32_t a2 = (color_b >> 24) & 0xFF;
|
uint32_t a2 = (color_b >> 24) & 0xFF;
|
||||||
uint32_t r3 = changeUIntScale(alpha, 0, 255, r2, r);
|
uint8_t r3 = changeUIntScale(alpha, 0, 255, r2, r);
|
||||||
uint32_t g3 = changeUIntScale(alpha, 0, 255, g2, g);
|
uint8_t g3 = changeUIntScale(alpha, 0, 255, g2, g);
|
||||||
uint32_t b3 = changeUIntScale(alpha, 0, 255, b2, b);
|
uint8_t b3 = changeUIntScale(alpha, 0, 255, b2, b);
|
||||||
uint32_t a3 = changeUIntScale(alpha, 0, 255, a2, a);
|
uint8_t a3 = changeUIntScale(alpha, 0, 255, a2, a);
|
||||||
uint32_t rgb = (a3 << 24) | (r3 << 16) | (g3 << 8) | b3;
|
uint32_t rgb = (a3 << 24) | (r3 << 16) | (g3 << 8) | b3;
|
||||||
be_pushint(vm, rgb);
|
be_pushint(vm, rgb);
|
||||||
be_return(vm);
|
be_return(vm);
|
||||||
@ -97,9 +97,9 @@ extern "C" {
|
|||||||
uint32_t fore_g = (fore_argb >> 8) & 0xFF;
|
uint32_t fore_g = (fore_argb >> 8) & 0xFF;
|
||||||
uint32_t back_b = (back_argb ) & 0xFF;
|
uint32_t back_b = (back_argb ) & 0xFF;
|
||||||
uint32_t fore_b = (fore_argb ) & 0xFF;
|
uint32_t fore_b = (fore_argb ) & 0xFF;
|
||||||
uint32_t dest_r_new = changeUIntScale(fore_alpha, 0, 255, fore_r, back_r);
|
uint8_t dest_r_new = changeUIntScale(fore_alpha, 0, 255, fore_r, back_r);
|
||||||
uint32_t dest_g_new = changeUIntScale(fore_alpha, 0, 255, fore_g, back_g);
|
uint8_t dest_g_new = changeUIntScale(fore_alpha, 0, 255, fore_g, back_g);
|
||||||
uint32_t dest_b_new = changeUIntScale(fore_alpha, 0, 255, fore_b, back_b);
|
uint8_t dest_b_new = changeUIntScale(fore_alpha, 0, 255, fore_b, back_b);
|
||||||
dest_rgb_new = (dest_r_new << 16) | (dest_g_new << 8) | dest_b_new;
|
dest_rgb_new = (dest_r_new << 16) | (dest_g_new << 8) | dest_b_new;
|
||||||
}
|
}
|
||||||
dest[i] = dest_rgb_new;
|
dest[i] = dest_rgb_new;
|
||||||
@ -135,7 +135,7 @@ extern "C" {
|
|||||||
|
|
||||||
// Leds_frame.paste_pixels(neopixel:bytes(), led_buffer:bytes(), bri:int 0..100, gamma:bool)
|
// Leds_frame.paste_pixels(neopixel:bytes(), led_buffer:bytes(), bri:int 0..100, gamma:bool)
|
||||||
//
|
//
|
||||||
// Copy from ARGB buffer to GRB
|
// Copy from ARGB buffer to RGB
|
||||||
int32_t be_leds_paste_pixels(bvm *vm);
|
int32_t be_leds_paste_pixels(bvm *vm);
|
||||||
int32_t be_leds_paste_pixels(bvm *vm) {
|
int32_t be_leds_paste_pixels(bvm *vm) {
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
@ -162,8 +162,8 @@ extern "C" {
|
|||||||
uint32_t src_r = (src_argb >> 16) & 0xFF;
|
uint32_t src_r = (src_argb >> 16) & 0xFF;
|
||||||
uint32_t src_g = (src_argb >> 8) & 0xFF;
|
uint32_t src_g = (src_argb >> 8) & 0xFF;
|
||||||
uint32_t src_b = (src_argb ) & 0xFF;
|
uint32_t src_b = (src_argb ) & 0xFF;
|
||||||
dest_buf[i * 3 + 0] = src_g;
|
dest_buf[i * 3 + 0] = src_r;
|
||||||
dest_buf[i * 3 + 1] = src_r;
|
dest_buf[i * 3 + 1] = src_g;
|
||||||
dest_buf[i * 3 + 2] = src_b;
|
dest_buf[i * 3 + 2] = src_b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -197,8 +197,8 @@ matter.IM_WriteResponse = Matter_IM_WriteResponse
|
|||||||
# This version pull the attributes in lazy mode, only when response is computed
|
# This version pull the attributes in lazy mode, only when response is computed
|
||||||
#################################################################################
|
#################################################################################
|
||||||
class Matter_IM_ReportData_Pull : Matter_IM_Message
|
class Matter_IM_ReportData_Pull : Matter_IM_Message
|
||||||
static var MAX_MESSAGE = 1200 # max bytes size for a single TLV worklaod
|
static var MAX_MESSAGE = 1150 # max bytes size for a single TLV worklaod
|
||||||
# the maximum MTU is 1280, which leaves 80 bytes for the rest of the message
|
# the maximum MTU is 1280, which leaves 130 bytes for the rest of the message
|
||||||
# section 4.4.4 (p. 114)
|
# section 4.4.4 (p. 114)
|
||||||
# note: `self.data` (bytes or nil) is containing any remaining responses that could not fit in previous packets
|
# note: `self.data` (bytes or nil) is containing any remaining responses that could not fit in previous packets
|
||||||
var generator_or_arr # a PathGenerator or an array of PathGenerator
|
var generator_or_arr # a PathGenerator or an array of PathGenerator
|
||||||
|
|||||||
@ -375,7 +375,7 @@ class Matter_Frame
|
|||||||
# recompute nonce
|
# recompute nonce
|
||||||
var n = self.message_handler._n_bytes # use cached bytes() object to avoid allocation
|
var n = self.message_handler._n_bytes # use cached bytes() object to avoid allocation
|
||||||
n.clear()
|
n.clear()
|
||||||
n.add(self.flags, 1)
|
n.add(self.sec_flags, 1)
|
||||||
n.add(self.message_counter, 4)
|
n.add(self.message_counter, 4)
|
||||||
if self.source_node_id
|
if self.source_node_id
|
||||||
n .. self.source_node_id
|
n .. self.source_node_id
|
||||||
@ -426,7 +426,7 @@ class Matter_Frame
|
|||||||
# recompute nonce
|
# recompute nonce
|
||||||
var n = self.message_handler._n_bytes # use cached bytes() object to avoid allocation
|
var n = self.message_handler._n_bytes # use cached bytes() object to avoid allocation
|
||||||
n.clear()
|
n.clear()
|
||||||
n.add(self.flags, 1)
|
n.add(self.sec_flags, 1)
|
||||||
n.add(self.message_counter, 4)
|
n.add(self.message_counter, 4)
|
||||||
if session.is_CASE() && session.get_device_id()
|
if session.is_CASE() && session.get_device_id()
|
||||||
n .. session.get_device_id()
|
n .. session.get_device_id()
|
||||||
|
|||||||
@ -1095,7 +1095,7 @@ be_local_class(Matter_IM_ReportData_Pull,
|
|||||||
{ be_const_key_weak(status_ok_received, -1), be_const_closure(class_Matter_IM_ReportData_Pull_status_ok_received_closure) },
|
{ be_const_key_weak(status_ok_received, -1), be_const_closure(class_Matter_IM_ReportData_Pull_status_ok_received_closure) },
|
||||||
{ be_const_key_weak(data_ev, -1), be_const_var(4) },
|
{ be_const_key_weak(data_ev, -1), be_const_var(4) },
|
||||||
{ be_const_key_weak(suppress_response, 8), be_const_var(3) },
|
{ be_const_key_weak(suppress_response, 8), be_const_var(3) },
|
||||||
{ be_const_key_weak(MAX_MESSAGE, -1), be_const_int(1200) },
|
{ be_const_key_weak(MAX_MESSAGE, -1), be_const_int(1150) },
|
||||||
{ be_const_key_weak(set_suppress_response, -1), be_const_closure(class_Matter_IM_ReportData_Pull_set_suppress_response_closure) },
|
{ be_const_key_weak(set_suppress_response, -1), be_const_closure(class_Matter_IM_ReportData_Pull_set_suppress_response_closure) },
|
||||||
{ be_const_key_weak(set_subscription_id, -1), be_const_closure(class_Matter_IM_ReportData_Pull_set_subscription_id_closure) },
|
{ be_const_key_weak(set_subscription_id, -1), be_const_closure(class_Matter_IM_ReportData_Pull_set_subscription_id_closure) },
|
||||||
{ be_const_key_weak(generator_or_arr, 5), be_const_var(0) },
|
{ be_const_key_weak(generator_or_arr, 5), be_const_var(0) },
|
||||||
|
|||||||
@ -16,7 +16,7 @@ static const bvalue be_ktab_class_Matter_Frame[73] = {
|
|||||||
/* K7 */ be_nested_str_weak(_n_bytes),
|
/* K7 */ be_nested_str_weak(_n_bytes),
|
||||||
/* K8 */ be_nested_str_weak(clear),
|
/* K8 */ be_nested_str_weak(clear),
|
||||||
/* K9 */ be_nested_str_weak(add),
|
/* K9 */ be_nested_str_weak(add),
|
||||||
/* K10 */ be_nested_str_weak(flags),
|
/* K10 */ be_nested_str_weak(sec_flags),
|
||||||
/* K11 */ be_const_int(1),
|
/* K11 */ be_const_int(1),
|
||||||
/* K12 */ be_nested_str_weak(message_counter),
|
/* K12 */ be_nested_str_weak(message_counter),
|
||||||
/* K13 */ be_nested_str_weak(is_CASE),
|
/* K13 */ be_nested_str_weak(is_CASE),
|
||||||
@ -27,12 +27,12 @@ static const bvalue be_ktab_class_Matter_Frame[73] = {
|
|||||||
/* K18 */ be_const_int(0),
|
/* K18 */ be_const_int(0),
|
||||||
/* K19 */ be_nested_str_weak(remote_ip),
|
/* K19 */ be_nested_str_weak(remote_ip),
|
||||||
/* K20 */ be_nested_str_weak(remote_port),
|
/* K20 */ be_nested_str_weak(remote_port),
|
||||||
/* K21 */ be_nested_str_weak(flag_s),
|
/* K21 */ be_nested_str_weak(flags),
|
||||||
/* K22 */ be_nested_str_weak(flag_dsiz),
|
/* K22 */ be_nested_str_weak(flag_s),
|
||||||
/* K23 */ be_const_int(3),
|
/* K23 */ be_nested_str_weak(flag_dsiz),
|
||||||
/* K24 */ be_nested_str_weak(local_session_id),
|
/* K24 */ be_const_int(3),
|
||||||
/* K25 */ be_const_int(2),
|
/* K25 */ be_nested_str_weak(local_session_id),
|
||||||
/* K26 */ be_nested_str_weak(sec_flags),
|
/* K26 */ be_const_int(2),
|
||||||
/* K27 */ be_nested_str_weak(sec_p),
|
/* K27 */ be_nested_str_weak(sec_p),
|
||||||
/* K28 */ be_nested_str_weak(sec_c),
|
/* K28 */ be_nested_str_weak(sec_c),
|
||||||
/* K29 */ be_nested_str_weak(sec_sesstype),
|
/* K29 */ be_nested_str_weak(sec_sesstype),
|
||||||
@ -260,83 +260,83 @@ be_local_closure(class_Matter_Frame_encode_frame, /* name */
|
|||||||
0x00100805, // 000B ADD R4 R4 R5
|
0x00100805, // 000B ADD R4 R4 R5
|
||||||
0x7C0C0200, // 000C CALL R3 1
|
0x7C0C0200, // 000C CALL R3 1
|
||||||
0x5C080600, // 000D MOVE R2 R3
|
0x5C080600, // 000D MOVE R2 R3
|
||||||
0x880C010A, // 000E GETMBR R3 R0 K10
|
0x880C0115, // 000E GETMBR R3 R0 K21
|
||||||
0x4C100000, // 000F LDNIL R4
|
0x4C100000, // 000F LDNIL R4
|
||||||
0x1C0C0604, // 0010 EQ R3 R3 R4
|
0x1C0C0604, // 0010 EQ R3 R3 R4
|
||||||
0x780E000D, // 0011 JMPF R3 #0020
|
0x780E000D, // 0011 JMPF R3 #0020
|
||||||
0x90021512, // 0012 SETMBR R0 K10 K18
|
0x90022B12, // 0012 SETMBR R0 K21 K18
|
||||||
0x880C0115, // 0013 GETMBR R3 R0 K21
|
0x880C0116, // 0013 GETMBR R3 R0 K22
|
||||||
0x780E0003, // 0014 JMPF R3 #0019
|
0x780E0003, // 0014 JMPF R3 #0019
|
||||||
0x880C010A, // 0015 GETMBR R3 R0 K10
|
0x880C0115, // 0015 GETMBR R3 R0 K21
|
||||||
0x54120003, // 0016 LDINT R4 4
|
0x54120003, // 0016 LDINT R4 4
|
||||||
0x300C0604, // 0017 OR R3 R3 R4
|
0x300C0604, // 0017 OR R3 R3 R4
|
||||||
0x90021403, // 0018 SETMBR R0 K10 R3
|
0x90022A03, // 0018 SETMBR R0 K21 R3
|
||||||
0x880C0116, // 0019 GETMBR R3 R0 K22
|
0x880C0117, // 0019 GETMBR R3 R0 K23
|
||||||
0x780E0004, // 001A JMPF R3 #0020
|
0x780E0004, // 001A JMPF R3 #0020
|
||||||
0x880C010A, // 001B GETMBR R3 R0 K10
|
0x880C0115, // 001B GETMBR R3 R0 K21
|
||||||
0x88100116, // 001C GETMBR R4 R0 K22
|
0x88100117, // 001C GETMBR R4 R0 K23
|
||||||
0x2C100917, // 001D AND R4 R4 K23
|
0x2C100918, // 001D AND R4 R4 K24
|
||||||
0x300C0604, // 001E OR R3 R3 R4
|
0x300C0604, // 001E OR R3 R3 R4
|
||||||
0x90021403, // 001F SETMBR R0 K10 R3
|
0x90022A03, // 001F SETMBR R0 K21 R3
|
||||||
0x8C0C0509, // 0020 GETMET R3 R2 K9
|
0x8C0C0509, // 0020 GETMET R3 R2 K9
|
||||||
0x8814010A, // 0021 GETMBR R5 R0 K10
|
0x88140115, // 0021 GETMBR R5 R0 K21
|
||||||
0x5818000B, // 0022 LDCONST R6 K11
|
0x5818000B, // 0022 LDCONST R6 K11
|
||||||
0x7C0C0600, // 0023 CALL R3 3
|
0x7C0C0600, // 0023 CALL R3 3
|
||||||
0x8C0C0509, // 0024 GETMET R3 R2 K9
|
0x8C0C0509, // 0024 GETMET R3 R2 K9
|
||||||
0x88140118, // 0025 GETMBR R5 R0 K24
|
0x88140119, // 0025 GETMBR R5 R0 K25
|
||||||
0x78160001, // 0026 JMPF R5 #0029
|
0x78160001, // 0026 JMPF R5 #0029
|
||||||
0x88140118, // 0027 GETMBR R5 R0 K24
|
0x88140119, // 0027 GETMBR R5 R0 K25
|
||||||
0x70020000, // 0028 JMP #002A
|
0x70020000, // 0028 JMP #002A
|
||||||
0x58140012, // 0029 LDCONST R5 K18
|
0x58140012, // 0029 LDCONST R5 K18
|
||||||
0x58180019, // 002A LDCONST R6 K25
|
0x5818001A, // 002A LDCONST R6 K26
|
||||||
0x7C0C0600, // 002B CALL R3 3
|
0x7C0C0600, // 002B CALL R3 3
|
||||||
0x880C011A, // 002C GETMBR R3 R0 K26
|
0x880C010A, // 002C GETMBR R3 R0 K10
|
||||||
0x4C100000, // 002D LDNIL R4
|
0x4C100000, // 002D LDNIL R4
|
||||||
0x1C0C0604, // 002E EQ R3 R3 R4
|
0x1C0C0604, // 002E EQ R3 R3 R4
|
||||||
0x780E0013, // 002F JMPF R3 #0044
|
0x780E0013, // 002F JMPF R3 #0044
|
||||||
0x90023512, // 0030 SETMBR R0 K26 K18
|
0x90021512, // 0030 SETMBR R0 K10 K18
|
||||||
0x880C011B, // 0031 GETMBR R3 R0 K27
|
0x880C011B, // 0031 GETMBR R3 R0 K27
|
||||||
0x780E0003, // 0032 JMPF R3 #0037
|
0x780E0003, // 0032 JMPF R3 #0037
|
||||||
0x880C011A, // 0033 GETMBR R3 R0 K26
|
0x880C010A, // 0033 GETMBR R3 R0 K10
|
||||||
0x5412007F, // 0034 LDINT R4 128
|
0x5412007F, // 0034 LDINT R4 128
|
||||||
0x300C0604, // 0035 OR R3 R3 R4
|
0x300C0604, // 0035 OR R3 R3 R4
|
||||||
0x90023403, // 0036 SETMBR R0 K26 R3
|
0x90021403, // 0036 SETMBR R0 K10 R3
|
||||||
0x880C011C, // 0037 GETMBR R3 R0 K28
|
0x880C011C, // 0037 GETMBR R3 R0 K28
|
||||||
0x780E0003, // 0038 JMPF R3 #003D
|
0x780E0003, // 0038 JMPF R3 #003D
|
||||||
0x880C011A, // 0039 GETMBR R3 R0 K26
|
0x880C010A, // 0039 GETMBR R3 R0 K10
|
||||||
0x5412003F, // 003A LDINT R4 64
|
0x5412003F, // 003A LDINT R4 64
|
||||||
0x300C0604, // 003B OR R3 R3 R4
|
0x300C0604, // 003B OR R3 R3 R4
|
||||||
0x90023403, // 003C SETMBR R0 K26 R3
|
0x90021403, // 003C SETMBR R0 K10 R3
|
||||||
0x880C011D, // 003D GETMBR R3 R0 K29
|
0x880C011D, // 003D GETMBR R3 R0 K29
|
||||||
0x780E0004, // 003E JMPF R3 #0044
|
0x780E0004, // 003E JMPF R3 #0044
|
||||||
0x880C011A, // 003F GETMBR R3 R0 K26
|
0x880C010A, // 003F GETMBR R3 R0 K10
|
||||||
0x8810011D, // 0040 GETMBR R4 R0 K29
|
0x8810011D, // 0040 GETMBR R4 R0 K29
|
||||||
0x2C100917, // 0041 AND R4 R4 K23
|
0x2C100918, // 0041 AND R4 R4 K24
|
||||||
0x300C0604, // 0042 OR R3 R3 R4
|
0x300C0604, // 0042 OR R3 R3 R4
|
||||||
0x90023403, // 0043 SETMBR R0 K26 R3
|
0x90021403, // 0043 SETMBR R0 K10 R3
|
||||||
0x8C0C0509, // 0044 GETMET R3 R2 K9
|
0x8C0C0509, // 0044 GETMET R3 R2 K9
|
||||||
0x8814011A, // 0045 GETMBR R5 R0 K26
|
0x8814010A, // 0045 GETMBR R5 R0 K10
|
||||||
0x5818000B, // 0046 LDCONST R6 K11
|
0x5818000B, // 0046 LDCONST R6 K11
|
||||||
0x7C0C0600, // 0047 CALL R3 3
|
0x7C0C0600, // 0047 CALL R3 3
|
||||||
0x8C0C0509, // 0048 GETMET R3 R2 K9
|
0x8C0C0509, // 0048 GETMET R3 R2 K9
|
||||||
0x8814010C, // 0049 GETMBR R5 R0 K12
|
0x8814010C, // 0049 GETMBR R5 R0 K12
|
||||||
0x541A0003, // 004A LDINT R6 4
|
0x541A0003, // 004A LDINT R6 4
|
||||||
0x7C0C0600, // 004B CALL R3 3
|
0x7C0C0600, // 004B CALL R3 3
|
||||||
0x880C0115, // 004C GETMBR R3 R0 K21
|
0x880C0116, // 004C GETMBR R3 R0 K22
|
||||||
0x780E0001, // 004D JMPF R3 #0050
|
0x780E0001, // 004D JMPF R3 #0050
|
||||||
0x880C011E, // 004E GETMBR R3 R0 K30
|
0x880C011E, // 004E GETMBR R3 R0 K30
|
||||||
0x400C0403, // 004F CONNECT R3 R2 R3
|
0x400C0403, // 004F CONNECT R3 R2 R3
|
||||||
0x880C0116, // 0050 GETMBR R3 R0 K22
|
0x880C0117, // 0050 GETMBR R3 R0 K23
|
||||||
0x1C0C070B, // 0051 EQ R3 R3 K11
|
0x1C0C070B, // 0051 EQ R3 R3 K11
|
||||||
0x780E0001, // 0052 JMPF R3 #0055
|
0x780E0001, // 0052 JMPF R3 #0055
|
||||||
0x880C011F, // 0053 GETMBR R3 R0 K31
|
0x880C011F, // 0053 GETMBR R3 R0 K31
|
||||||
0x400C0403, // 0054 CONNECT R3 R2 R3
|
0x400C0403, // 0054 CONNECT R3 R2 R3
|
||||||
0x880C0116, // 0055 GETMBR R3 R0 K22
|
0x880C0117, // 0055 GETMBR R3 R0 K23
|
||||||
0x1C0C0719, // 0056 EQ R3 R3 K25
|
0x1C0C071A, // 0056 EQ R3 R3 K26
|
||||||
0x780E0003, // 0057 JMPF R3 #005C
|
0x780E0003, // 0057 JMPF R3 #005C
|
||||||
0x8C0C0509, // 0058 GETMET R3 R2 K9
|
0x8C0C0509, // 0058 GETMET R3 R2 K9
|
||||||
0x88140120, // 0059 GETMBR R5 R0 K32
|
0x88140120, // 0059 GETMBR R5 R0 K32
|
||||||
0x58180019, // 005A LDCONST R6 K25
|
0x5818001A, // 005A LDCONST R6 K26
|
||||||
0x7C0C0600, // 005B CALL R3 3
|
0x7C0C0600, // 005B CALL R3 3
|
||||||
0x600C000C, // 005C GETGBL R3 G12
|
0x600C000C, // 005C GETGBL R3 G12
|
||||||
0x5C100400, // 005D MOVE R4 R2
|
0x5C100400, // 005D MOVE R4 R2
|
||||||
@ -362,7 +362,7 @@ be_local_closure(class_Matter_Frame_encode_frame, /* name */
|
|||||||
0x880C0124, // 0071 GETMBR R3 R0 K36
|
0x880C0124, // 0071 GETMBR R3 R0 K36
|
||||||
0x780E0002, // 0072 JMPF R3 #0076
|
0x780E0002, // 0072 JMPF R3 #0076
|
||||||
0x880C0121, // 0073 GETMBR R3 R0 K33
|
0x880C0121, // 0073 GETMBR R3 R0 K33
|
||||||
0x300C0719, // 0074 OR R3 R3 K25
|
0x300C071A, // 0074 OR R3 R3 K26
|
||||||
0x90024203, // 0075 SETMBR R0 K33 R3
|
0x90024203, // 0075 SETMBR R0 K33 R3
|
||||||
0x880C0125, // 0076 GETMBR R3 R0 K37
|
0x880C0125, // 0076 GETMBR R3 R0 K37
|
||||||
0x780E0002, // 0077 JMPF R3 #007B
|
0x780E0002, // 0077 JMPF R3 #007B
|
||||||
@ -387,11 +387,11 @@ be_local_closure(class_Matter_Frame_encode_frame, /* name */
|
|||||||
0x2C140A06, // 008A AND R5 R5 R6
|
0x2C140A06, // 008A AND R5 R5 R6
|
||||||
0x70020000, // 008B JMP #008D
|
0x70020000, // 008B JMP #008D
|
||||||
0x58140012, // 008C LDCONST R5 K18
|
0x58140012, // 008C LDCONST R5 K18
|
||||||
0x58180019, // 008D LDCONST R6 K25
|
0x5818001A, // 008D LDCONST R6 K26
|
||||||
0x7C0C0600, // 008E CALL R3 3
|
0x7C0C0600, // 008E CALL R3 3
|
||||||
0x8C0C0509, // 008F GETMET R3 R2 K9
|
0x8C0C0509, // 008F GETMET R3 R2 K9
|
||||||
0x88140128, // 0090 GETMBR R5 R0 K40
|
0x88140128, // 0090 GETMBR R5 R0 K40
|
||||||
0x58180019, // 0091 LDCONST R6 K25
|
0x5818001A, // 0091 LDCONST R6 K26
|
||||||
0x7C0C0600, // 0092 CALL R3 3
|
0x7C0C0600, // 0092 CALL R3 3
|
||||||
0x880C0124, // 0093 GETMBR R3 R0 K36
|
0x880C0124, // 0093 GETMBR R3 R0 K36
|
||||||
0x780E0003, // 0094 JMPF R3 #0099
|
0x780E0003, // 0094 JMPF R3 #0099
|
||||||
@ -436,8 +436,8 @@ be_local_closure(class_Matter_Frame_decode_header, /* name */
|
|||||||
0x58140012, // 0003 LDCONST R5 K18
|
0x58140012, // 0003 LDCONST R5 K18
|
||||||
0x5818000B, // 0004 LDCONST R6 K11
|
0x5818000B, // 0004 LDCONST R6 K11
|
||||||
0x7C0C0600, // 0005 CALL R3 3
|
0x7C0C0600, // 0005 CALL R3 3
|
||||||
0x90021403, // 0006 SETMBR R0 K10 R3
|
0x90022A03, // 0006 SETMBR R0 K21 R3
|
||||||
0x880C010A, // 0007 GETMBR R3 R0 K10
|
0x880C0115, // 0007 GETMBR R3 R0 K21
|
||||||
0x541200F7, // 0008 LDINT R4 248
|
0x541200F7, // 0008 LDINT R4 248
|
||||||
0x2C0C0604, // 0009 AND R3 R3 R4
|
0x2C0C0604, // 0009 AND R3 R3 R4
|
||||||
0x200C0712, // 000A NE R3 R3 K18
|
0x200C0712, // 000A NE R3 R3 K18
|
||||||
@ -445,28 +445,28 @@ be_local_closure(class_Matter_Frame_decode_header, /* name */
|
|||||||
0x500C0000, // 000C LDBOOL R3 0 0
|
0x500C0000, // 000C LDBOOL R3 0 0
|
||||||
0x80040600, // 000D RET 1 R3
|
0x80040600, // 000D RET 1 R3
|
||||||
0x8C0C052C, // 000E GETMET R3 R2 K44
|
0x8C0C052C, // 000E GETMET R3 R2 K44
|
||||||
0x58140019, // 000F LDCONST R5 K25
|
0x5814001A, // 000F LDCONST R5 K26
|
||||||
0x5818000B, // 0010 LDCONST R6 K11
|
0x5818000B, // 0010 LDCONST R6 K11
|
||||||
0x7C0C0600, // 0011 CALL R3 3
|
0x7C0C0600, // 0011 CALL R3 3
|
||||||
0x90022A03, // 0012 SETMBR R0 K21 R3
|
0x90022C03, // 0012 SETMBR R0 K22 R3
|
||||||
0x8C0C052C, // 0013 GETMET R3 R2 K44
|
0x8C0C052C, // 0013 GETMET R3 R2 K44
|
||||||
0x58140012, // 0014 LDCONST R5 K18
|
0x58140012, // 0014 LDCONST R5 K18
|
||||||
0x58180019, // 0015 LDCONST R6 K25
|
0x5818001A, // 0015 LDCONST R6 K26
|
||||||
0x7C0C0600, // 0016 CALL R3 3
|
0x7C0C0600, // 0016 CALL R3 3
|
||||||
0x90022C03, // 0017 SETMBR R0 K22 R3
|
0x90022E03, // 0017 SETMBR R0 K23 R3
|
||||||
0x880C0116, // 0018 GETMBR R3 R0 K22
|
0x880C0117, // 0018 GETMBR R3 R0 K23
|
||||||
0x1C0C0717, // 0019 EQ R3 R3 K23
|
0x1C0C0718, // 0019 EQ R3 R3 K24
|
||||||
0x780E0001, // 001A JMPF R3 #001D
|
0x780E0001, // 001A JMPF R3 #001D
|
||||||
0x500C0000, // 001B LDBOOL R3 0 0
|
0x500C0000, // 001B LDBOOL R3 0 0
|
||||||
0x80040600, // 001C RET 1 R3
|
0x80040600, // 001C RET 1 R3
|
||||||
0x8C0C052B, // 001D GETMET R3 R2 K43
|
0x8C0C052B, // 001D GETMET R3 R2 K43
|
||||||
0x58140017, // 001E LDCONST R5 K23
|
0x58140018, // 001E LDCONST R5 K24
|
||||||
0x5818000B, // 001F LDCONST R6 K11
|
0x5818000B, // 001F LDCONST R6 K11
|
||||||
0x7C0C0600, // 0020 CALL R3 3
|
0x7C0C0600, // 0020 CALL R3 3
|
||||||
0x90023403, // 0021 SETMBR R0 K26 R3
|
0x90021403, // 0021 SETMBR R0 K10 R3
|
||||||
0x8C0C052C, // 0022 GETMET R3 R2 K44
|
0x8C0C052C, // 0022 GETMET R3 R2 K44
|
||||||
0x54160007, // 0023 LDINT R5 8
|
0x54160007, // 0023 LDINT R5 8
|
||||||
0x08162E05, // 0024 MUL R5 K23 R5
|
0x08163005, // 0024 MUL R5 K24 R5
|
||||||
0x541A0006, // 0025 LDINT R6 7
|
0x541A0006, // 0025 LDINT R6 7
|
||||||
0x00140A06, // 0026 ADD R5 R5 R6
|
0x00140A06, // 0026 ADD R5 R5 R6
|
||||||
0x5818000B, // 0027 LDCONST R6 K11
|
0x5818000B, // 0027 LDCONST R6 K11
|
||||||
@ -474,7 +474,7 @@ be_local_closure(class_Matter_Frame_decode_header, /* name */
|
|||||||
0x90023603, // 0029 SETMBR R0 K27 R3
|
0x90023603, // 0029 SETMBR R0 K27 R3
|
||||||
0x8C0C052C, // 002A GETMET R3 R2 K44
|
0x8C0C052C, // 002A GETMET R3 R2 K44
|
||||||
0x54160007, // 002B LDINT R5 8
|
0x54160007, // 002B LDINT R5 8
|
||||||
0x08162E05, // 002C MUL R5 K23 R5
|
0x08163005, // 002C MUL R5 K24 R5
|
||||||
0x541A0005, // 002D LDINT R6 6
|
0x541A0005, // 002D LDINT R6 6
|
||||||
0x00140A06, // 002E ADD R5 R5 R6
|
0x00140A06, // 002E ADD R5 R5 R6
|
||||||
0x5818000B, // 002F LDCONST R6 K11
|
0x5818000B, // 002F LDCONST R6 K11
|
||||||
@ -482,7 +482,7 @@ be_local_closure(class_Matter_Frame_decode_header, /* name */
|
|||||||
0x90023803, // 0031 SETMBR R0 K28 R3
|
0x90023803, // 0031 SETMBR R0 K28 R3
|
||||||
0x8C0C052C, // 0032 GETMET R3 R2 K44
|
0x8C0C052C, // 0032 GETMET R3 R2 K44
|
||||||
0x54160007, // 0033 LDINT R5 8
|
0x54160007, // 0033 LDINT R5 8
|
||||||
0x08162E05, // 0034 MUL R5 K23 R5
|
0x08163005, // 0034 MUL R5 K24 R5
|
||||||
0x541A0004, // 0035 LDINT R6 5
|
0x541A0004, // 0035 LDINT R6 5
|
||||||
0x00140A06, // 0036 ADD R5 R5 R6
|
0x00140A06, // 0036 ADD R5 R5 R6
|
||||||
0x5818000B, // 0037 LDCONST R6 K11
|
0x5818000B, // 0037 LDCONST R6 K11
|
||||||
@ -490,8 +490,8 @@ be_local_closure(class_Matter_Frame_decode_header, /* name */
|
|||||||
0x90025A03, // 0039 SETMBR R0 K45 R3
|
0x90025A03, // 0039 SETMBR R0 K45 R3
|
||||||
0x8C0C052C, // 003A GETMET R3 R2 K44
|
0x8C0C052C, // 003A GETMET R3 R2 K44
|
||||||
0x54160007, // 003B LDINT R5 8
|
0x54160007, // 003B LDINT R5 8
|
||||||
0x08162E05, // 003C MUL R5 K23 R5
|
0x08163005, // 003C MUL R5 K24 R5
|
||||||
0x58180019, // 003D LDCONST R6 K25
|
0x5818001A, // 003D LDCONST R6 K26
|
||||||
0x7C0C0600, // 003E CALL R3 3
|
0x7C0C0600, // 003E CALL R3 3
|
||||||
0x90023A03, // 003F SETMBR R0 K29 R3
|
0x90023A03, // 003F SETMBR R0 K29 R3
|
||||||
0x880C011D, // 0040 GETMBR R3 R0 K29
|
0x880C011D, // 0040 GETMBR R3 R0 K29
|
||||||
@ -501,9 +501,9 @@ be_local_closure(class_Matter_Frame_decode_header, /* name */
|
|||||||
0x80040600, // 0044 RET 1 R3
|
0x80040600, // 0044 RET 1 R3
|
||||||
0x8C0C052B, // 0045 GETMET R3 R2 K43
|
0x8C0C052B, // 0045 GETMET R3 R2 K43
|
||||||
0x5814000B, // 0046 LDCONST R5 K11
|
0x5814000B, // 0046 LDCONST R5 K11
|
||||||
0x58180019, // 0047 LDCONST R6 K25
|
0x5818001A, // 0047 LDCONST R6 K26
|
||||||
0x7C0C0600, // 0048 CALL R3 3
|
0x7C0C0600, // 0048 CALL R3 3
|
||||||
0x90023003, // 0049 SETMBR R0 K24 R3
|
0x90023203, // 0049 SETMBR R0 K25 R3
|
||||||
0x8C0C052B, // 004A GETMET R3 R2 K43
|
0x8C0C052B, // 004A GETMET R3 R2 K43
|
||||||
0x54160003, // 004B LDINT R5 4
|
0x54160003, // 004B LDINT R5 4
|
||||||
0x541A0003, // 004C LDINT R6 4
|
0x541A0003, // 004C LDINT R6 4
|
||||||
@ -511,7 +511,7 @@ be_local_closure(class_Matter_Frame_decode_header, /* name */
|
|||||||
0x90021803, // 004E SETMBR R0 K12 R3
|
0x90021803, // 004E SETMBR R0 K12 R3
|
||||||
0x540E0007, // 004F LDINT R3 8
|
0x540E0007, // 004F LDINT R3 8
|
||||||
0x00040203, // 0050 ADD R1 R1 R3
|
0x00040203, // 0050 ADD R1 R1 R3
|
||||||
0x880C0115, // 0051 GETMBR R3 R0 K21
|
0x880C0116, // 0051 GETMBR R3 R0 K22
|
||||||
0x780E0006, // 0052 JMPF R3 #005A
|
0x780E0006, // 0052 JMPF R3 #005A
|
||||||
0x540E0006, // 0053 LDINT R3 7
|
0x540E0006, // 0053 LDINT R3 7
|
||||||
0x000C0203, // 0054 ADD R3 R1 R3
|
0x000C0203, // 0054 ADD R3 R1 R3
|
||||||
@ -520,7 +520,7 @@ be_local_closure(class_Matter_Frame_decode_header, /* name */
|
|||||||
0x90023C03, // 0057 SETMBR R0 K30 R3
|
0x90023C03, // 0057 SETMBR R0 K30 R3
|
||||||
0x540E0007, // 0058 LDINT R3 8
|
0x540E0007, // 0058 LDINT R3 8
|
||||||
0x00040203, // 0059 ADD R1 R1 R3
|
0x00040203, // 0059 ADD R1 R1 R3
|
||||||
0x880C0116, // 005A GETMBR R3 R0 K22
|
0x880C0117, // 005A GETMBR R3 R0 K23
|
||||||
0x1C0C070B, // 005B EQ R3 R3 K11
|
0x1C0C070B, // 005B EQ R3 R3 K11
|
||||||
0x780E0007, // 005C JMPF R3 #0065
|
0x780E0007, // 005C JMPF R3 #0065
|
||||||
0x540E0006, // 005D LDINT R3 7
|
0x540E0006, // 005D LDINT R3 7
|
||||||
@ -531,22 +531,22 @@ be_local_closure(class_Matter_Frame_decode_header, /* name */
|
|||||||
0x540E0007, // 0062 LDINT R3 8
|
0x540E0007, // 0062 LDINT R3 8
|
||||||
0x00040203, // 0063 ADD R1 R1 R3
|
0x00040203, // 0063 ADD R1 R1 R3
|
||||||
0x70020008, // 0064 JMP #006E
|
0x70020008, // 0064 JMP #006E
|
||||||
0x880C0116, // 0065 GETMBR R3 R0 K22
|
0x880C0117, // 0065 GETMBR R3 R0 K23
|
||||||
0x1C0C0719, // 0066 EQ R3 R3 K25
|
0x1C0C071A, // 0066 EQ R3 R3 K26
|
||||||
0x780E0005, // 0067 JMPF R3 #006E
|
0x780E0005, // 0067 JMPF R3 #006E
|
||||||
0x8C0C052B, // 0068 GETMET R3 R2 K43
|
0x8C0C052B, // 0068 GETMET R3 R2 K43
|
||||||
0x5C140200, // 0069 MOVE R5 R1
|
0x5C140200, // 0069 MOVE R5 R1
|
||||||
0x58180019, // 006A LDCONST R6 K25
|
0x5818001A, // 006A LDCONST R6 K26
|
||||||
0x7C0C0600, // 006B CALL R3 3
|
0x7C0C0600, // 006B CALL R3 3
|
||||||
0x90024003, // 006C SETMBR R0 K32 R3
|
0x90024003, // 006C SETMBR R0 K32 R3
|
||||||
0x00040319, // 006D ADD R1 R1 K25
|
0x0004031A, // 006D ADD R1 R1 K26
|
||||||
0x880C012D, // 006E GETMBR R3 R0 K45
|
0x880C012D, // 006E GETMBR R3 R0 K45
|
||||||
0x780E0005, // 006F JMPF R3 #0076
|
0x780E0005, // 006F JMPF R3 #0076
|
||||||
0x8C0C052B, // 0070 GETMET R3 R2 K43
|
0x8C0C052B, // 0070 GETMET R3 R2 K43
|
||||||
0x5C140200, // 0071 MOVE R5 R1
|
0x5C140200, // 0071 MOVE R5 R1
|
||||||
0x58180019, // 0072 LDCONST R6 K25
|
0x5818001A, // 0072 LDCONST R6 K26
|
||||||
0x7C0C0600, // 0073 CALL R3 3
|
0x7C0C0600, // 0073 CALL R3 3
|
||||||
0x00100719, // 0074 ADD R4 R3 K25
|
0x0010071A, // 0074 ADD R4 R3 K26
|
||||||
0x00040204, // 0075 ADD R1 R1 R4
|
0x00040204, // 0075 ADD R1 R1 R4
|
||||||
0x90020801, // 0076 SETMBR R0 K4 R1
|
0x90020801, // 0076 SETMBR R0 K4 R1
|
||||||
0x500C0200, // 0077 LDBOOL R3 1 0
|
0x500C0200, // 0077 LDBOOL R3 1 0
|
||||||
@ -620,16 +620,16 @@ be_local_closure(class_Matter_Frame_build_response, /* name */
|
|||||||
0x900E2604, // 000A SETMBR R3 K19 R4
|
0x900E2604, // 000A SETMBR R3 K19 R4
|
||||||
0x88100114, // 000B GETMBR R4 R0 K20
|
0x88100114, // 000B GETMBR R4 R0 K20
|
||||||
0x900E2804, // 000C SETMBR R3 K20 R4
|
0x900E2804, // 000C SETMBR R3 K20 R4
|
||||||
0x88100115, // 000D GETMBR R4 R0 K21
|
0x88100116, // 000D GETMBR R4 R0 K22
|
||||||
0x78120003, // 000E JMPF R4 #0013
|
0x78120003, // 000E JMPF R4 #0013
|
||||||
0x900E2D0B, // 000F SETMBR R3 K22 K11
|
0x900E2F0B, // 000F SETMBR R3 K23 K11
|
||||||
0x8810011E, // 0010 GETMBR R4 R0 K30
|
0x8810011E, // 0010 GETMBR R4 R0 K30
|
||||||
0x900E3E04, // 0011 SETMBR R3 K31 R4
|
0x900E3E04, // 0011 SETMBR R3 K31 R4
|
||||||
0x70020000, // 0012 JMP #0014
|
0x70020000, // 0012 JMP #0014
|
||||||
0x900E2D12, // 0013 SETMBR R3 K22 K18
|
0x900E2F12, // 0013 SETMBR R3 K23 K18
|
||||||
0x88100100, // 0014 GETMBR R4 R0 K0
|
0x88100100, // 0014 GETMBR R4 R0 K0
|
||||||
0x900E0004, // 0015 SETMBR R3 K0 R4
|
0x900E0004, // 0015 SETMBR R3 K0 R4
|
||||||
0x88100118, // 0016 GETMBR R4 R0 K24
|
0x88100119, // 0016 GETMBR R4 R0 K25
|
||||||
0x20100912, // 0017 NE R4 R4 K18
|
0x20100912, // 0017 NE R4 R4 K18
|
||||||
0x7812000D, // 0018 JMPF R4 #0027
|
0x7812000D, // 0018 JMPF R4 #0027
|
||||||
0x88100100, // 0019 GETMBR R4 R0 K0
|
0x88100100, // 0019 GETMBR R4 R0 K0
|
||||||
@ -644,14 +644,14 @@ be_local_closure(class_Matter_Frame_build_response, /* name */
|
|||||||
0x900E1804, // 0022 SETMBR R3 K12 R4
|
0x900E1804, // 0022 SETMBR R3 K12 R4
|
||||||
0x88100100, // 0023 GETMBR R4 R0 K0
|
0x88100100, // 0023 GETMBR R4 R0 K0
|
||||||
0x88100932, // 0024 GETMBR R4 R4 K50
|
0x88100932, // 0024 GETMBR R4 R4 K50
|
||||||
0x900E3004, // 0025 SETMBR R3 K24 R4
|
0x900E3204, // 0025 SETMBR R3 K25 R4
|
||||||
0x70020005, // 0026 JMP #002D
|
0x70020005, // 0026 JMP #002D
|
||||||
0x88100100, // 0027 GETMBR R4 R0 K0
|
0x88100100, // 0027 GETMBR R4 R0 K0
|
||||||
0x88100934, // 0028 GETMBR R4 R4 K52
|
0x88100934, // 0028 GETMBR R4 R4 K52
|
||||||
0x8C100935, // 0029 GETMET R4 R4 K53
|
0x8C100935, // 0029 GETMET R4 R4 K53
|
||||||
0x7C100200, // 002A CALL R4 1
|
0x7C100200, // 002A CALL R4 1
|
||||||
0x900E1804, // 002B SETMBR R3 K12 R4
|
0x900E1804, // 002B SETMBR R3 K12 R4
|
||||||
0x900E3112, // 002C SETMBR R3 K24 K18
|
0x900E3312, // 002C SETMBR R3 K25 K18
|
||||||
0x88100125, // 002D GETMBR R4 R0 K37
|
0x88100125, // 002D GETMBR R4 R0 K37
|
||||||
0x78120001, // 002E JMPF R4 #0031
|
0x78120001, // 002E JMPF R4 #0031
|
||||||
0x58100012, // 002F LDCONST R4 K18
|
0x58100012, // 002F LDCONST R4 K18
|
||||||
@ -673,7 +673,7 @@ be_local_closure(class_Matter_Frame_build_response, /* name */
|
|||||||
0x70020000, // 003F JMP #0041
|
0x70020000, // 003F JMP #0041
|
||||||
0x58100012, // 0040 LDCONST R4 K18
|
0x58100012, // 0040 LDCONST R4 K18
|
||||||
0x900E4604, // 0041 SETMBR R3 K35 R4
|
0x900E4604, // 0041 SETMBR R3 K35 R4
|
||||||
0x88100718, // 0042 GETMBR R4 R3 K24
|
0x88100719, // 0042 GETMBR R4 R3 K25
|
||||||
0x1C100912, // 0043 EQ R4 R4 K18
|
0x1C100912, // 0043 EQ R4 R4 K18
|
||||||
0x78120013, // 0044 JMPF R4 #0059
|
0x78120013, // 0044 JMPF R4 #0059
|
||||||
0xB8125C00, // 0045 GETNGBL R4 K46
|
0xB8125C00, // 0045 GETNGBL R4 K46
|
||||||
@ -691,10 +691,10 @@ be_local_closure(class_Matter_Frame_build_response, /* name */
|
|||||||
0x60180018, // 0051 GETGBL R6 G24
|
0x60180018, // 0051 GETGBL R6 G24
|
||||||
0x581C0039, // 0052 LDCONST R7 K57
|
0x581C0039, // 0052 LDCONST R7 K57
|
||||||
0x88200700, // 0053 GETMBR R8 R3 K0
|
0x88200700, // 0053 GETMBR R8 R3 K0
|
||||||
0x88201118, // 0054 GETMBR R8 R8 K24
|
0x88201119, // 0054 GETMBR R8 R8 K25
|
||||||
0x5C240800, // 0055 MOVE R9 R4
|
0x5C240800, // 0055 MOVE R9 R4
|
||||||
0x7C180600, // 0056 CALL R6 3
|
0x7C180600, // 0056 CALL R6 3
|
||||||
0x581C0017, // 0057 LDCONST R7 K23
|
0x581C0018, // 0057 LDCONST R7 K24
|
||||||
0x7C140400, // 0058 CALL R5 2
|
0x7C140400, // 0058 CALL R5 2
|
||||||
0x80040600, // 0059 RET 1 R3
|
0x80040600, // 0059 RET 1 R3
|
||||||
})
|
})
|
||||||
@ -731,7 +731,7 @@ be_local_closure(class_Matter_Frame_decrypt, /* name */
|
|||||||
0x781E002B, // 0008 JMPF R7 #0035
|
0x781E002B, // 0008 JMPF R7 #0035
|
||||||
0xB81E7000, // 0009 GETNGBL R7 K56
|
0xB81E7000, // 0009 GETNGBL R7 K56
|
||||||
0x5820003B, // 000A LDCONST R8 K59
|
0x5820003B, // 000A LDCONST R8 K59
|
||||||
0x58240019, // 000B LDCONST R9 K25
|
0x5824001A, // 000B LDCONST R9 K26
|
||||||
0x7C1C0400, // 000C CALL R7 2
|
0x7C1C0400, // 000C CALL R7 2
|
||||||
0x8C1C053C, // 000D GETMET R7 R2 K60
|
0x8C1C053C, // 000D GETMET R7 R2 K60
|
||||||
0x7C1C0200, // 000E CALL R7 1
|
0x7C1C0200, // 000E CALL R7 1
|
||||||
@ -741,7 +741,7 @@ be_local_closure(class_Matter_Frame_decrypt, /* name */
|
|||||||
0x60240015, // 0012 GETGBL R9 G21
|
0x60240015, // 0012 GETGBL R9 G21
|
||||||
0x7C240000, // 0013 CALL R9 0
|
0x7C240000, // 0013 CALL R9 0
|
||||||
0x8C241309, // 0014 GETMET R9 R9 K9
|
0x8C241309, // 0014 GETMET R9 R9 K9
|
||||||
0x882C0118, // 0015 GETMBR R11 R0 K24
|
0x882C0119, // 0015 GETMBR R11 R0 K25
|
||||||
0x5431FFFD, // 0016 LDINT R12 -2
|
0x5431FFFD, // 0016 LDINT R12 -2
|
||||||
0x7C240600, // 0017 CALL R9 3
|
0x7C240600, // 0017 CALL R9 3
|
||||||
0x542A0004, // 0018 LDINT R10 5
|
0x542A0004, // 0018 LDINT R10 5
|
||||||
@ -761,10 +761,10 @@ be_local_closure(class_Matter_Frame_decrypt, /* name */
|
|||||||
0x8C30193F, // 0026 GETMET R12 R12 K63
|
0x8C30193F, // 0026 GETMET R12 R12 K63
|
||||||
0x5C381400, // 0027 MOVE R14 R10
|
0x5C381400, // 0027 MOVE R14 R10
|
||||||
0x5C3C1200, // 0028 MOVE R15 R9
|
0x5C3C1200, // 0028 MOVE R15 R9
|
||||||
0x58400019, // 0029 LDCONST R16 K25
|
0x5840001A, // 0029 LDCONST R16 K26
|
||||||
0x7C300800, // 002A CALL R12 4
|
0x7C300800, // 002A CALL R12 4
|
||||||
0x5C2C1800, // 002B MOVE R11 R12
|
0x5C2C1800, // 002B MOVE R11 R12
|
||||||
0x40322517, // 002C CONNECT R12 K18 K23
|
0x40322518, // 002C CONNECT R12 K18 K24
|
||||||
0x88340103, // 002D GETMBR R13 R0 K3
|
0x88340103, // 002D GETMBR R13 R0 K3
|
||||||
0x94301A0C, // 002E GETIDX R12 R13 R12
|
0x94301A0C, // 002E GETIDX R12 R13 R12
|
||||||
0x0030180B, // 002F ADD R12 R12 R11
|
0x0030180B, // 002F ADD R12 R12 R11
|
||||||
@ -832,7 +832,7 @@ be_local_closure(class_Matter_Frame_decrypt, /* name */
|
|||||||
0x70020003, // 006D JMP #0072
|
0x70020003, // 006D JMP #0072
|
||||||
0xB8267000, // 006E GETNGBL R9 K56
|
0xB8267000, // 006E GETNGBL R9 K56
|
||||||
0x58280042, // 006F LDCONST R10 K66
|
0x58280042, // 006F LDCONST R10 K66
|
||||||
0x582C0017, // 0070 LDCONST R11 K23
|
0x582C0018, // 0070 LDCONST R11 K24
|
||||||
0x7C240400, // 0071 CALL R9 2
|
0x7C240400, // 0071 CALL R9 2
|
||||||
0x80041000, // 0072 RET 1 R8
|
0x80041000, // 0072 RET 1 R8
|
||||||
})
|
})
|
||||||
@ -867,13 +867,13 @@ be_local_closure(class_Matter_Frame_build_standalone_ack, /* name */
|
|||||||
0x900A2603, // 0006 SETMBR R2 K19 R3
|
0x900A2603, // 0006 SETMBR R2 K19 R3
|
||||||
0x880C0114, // 0007 GETMBR R3 R0 K20
|
0x880C0114, // 0007 GETMBR R3 R0 K20
|
||||||
0x900A2803, // 0008 SETMBR R2 K20 R3
|
0x900A2803, // 0008 SETMBR R2 K20 R3
|
||||||
0x880C0115, // 0009 GETMBR R3 R0 K21
|
0x880C0116, // 0009 GETMBR R3 R0 K22
|
||||||
0x780E0003, // 000A JMPF R3 #000F
|
0x780E0003, // 000A JMPF R3 #000F
|
||||||
0x900A2D0B, // 000B SETMBR R2 K22 K11
|
0x900A2F0B, // 000B SETMBR R2 K23 K11
|
||||||
0x880C011E, // 000C GETMBR R3 R0 K30
|
0x880C011E, // 000C GETMBR R3 R0 K30
|
||||||
0x900A3E03, // 000D SETMBR R2 K31 R3
|
0x900A3E03, // 000D SETMBR R2 K31 R3
|
||||||
0x70020000, // 000E JMP #0010
|
0x70020000, // 000E JMP #0010
|
||||||
0x900A2D12, // 000F SETMBR R2 K22 K18
|
0x900A2F12, // 000F SETMBR R2 K23 K18
|
||||||
0x880C0100, // 0010 GETMBR R3 R0 K0
|
0x880C0100, // 0010 GETMBR R3 R0 K0
|
||||||
0x900A0003, // 0011 SETMBR R2 K0 R3
|
0x900A0003, // 0011 SETMBR R2 K0 R3
|
||||||
0x880C0100, // 0012 GETMBR R3 R0 K0
|
0x880C0100, // 0012 GETMBR R3 R0 K0
|
||||||
@ -882,7 +882,7 @@ be_local_closure(class_Matter_Frame_build_standalone_ack, /* name */
|
|||||||
0x900A1803, // 0015 SETMBR R2 K12 R3
|
0x900A1803, // 0015 SETMBR R2 K12 R3
|
||||||
0x880C0100, // 0016 GETMBR R3 R0 K0
|
0x880C0100, // 0016 GETMBR R3 R0 K0
|
||||||
0x880C0732, // 0017 GETMBR R3 R3 K50
|
0x880C0732, // 0017 GETMBR R3 R3 K50
|
||||||
0x900A3003, // 0018 SETMBR R2 K24 R3
|
0x900A3203, // 0018 SETMBR R2 K25 R3
|
||||||
0x880C0125, // 0019 GETMBR R3 R0 K37
|
0x880C0125, // 0019 GETMBR R3 R0 K37
|
||||||
0x780E0001, // 001A JMPF R3 #001D
|
0x780E0001, // 001A JMPF R3 #001D
|
||||||
0x580C0012, // 001B LDCONST R3 K18
|
0x580C0012, // 001B LDCONST R3 K18
|
||||||
@ -939,7 +939,7 @@ be_local_closure(class_Matter_Frame_initiate_response, /* name */
|
|||||||
0x90122606, // 000A SETMBR R4 K19 R6
|
0x90122606, // 000A SETMBR R4 K19 R6
|
||||||
0x88180345, // 000B GETMBR R6 R1 K69
|
0x88180345, // 000B GETMBR R6 R1 K69
|
||||||
0x90122806, // 000C SETMBR R4 K20 R6
|
0x90122806, // 000C SETMBR R4 K20 R6
|
||||||
0x90122D12, // 000D SETMBR R4 K22 K18
|
0x90122F12, // 000D SETMBR R4 K23 K18
|
||||||
0x90120001, // 000E SETMBR R4 K0 R1
|
0x90120001, // 000E SETMBR R4 K0 R1
|
||||||
0x78060008, // 000F JMPF R1 #0019
|
0x78060008, // 000F JMPF R1 #0019
|
||||||
0x88180332, // 0010 GETMBR R6 R1 K50
|
0x88180332, // 0010 GETMBR R6 R1 K50
|
||||||
@ -949,13 +949,13 @@ be_local_closure(class_Matter_Frame_initiate_response, /* name */
|
|||||||
0x7C180200, // 0014 CALL R6 1
|
0x7C180200, // 0014 CALL R6 1
|
||||||
0x90121806, // 0015 SETMBR R4 K12 R6
|
0x90121806, // 0015 SETMBR R4 K12 R6
|
||||||
0x88180332, // 0016 GETMBR R6 R1 K50
|
0x88180332, // 0016 GETMBR R6 R1 K50
|
||||||
0x90123006, // 0017 SETMBR R4 K24 R6
|
0x90123206, // 0017 SETMBR R4 K25 R6
|
||||||
0x70020004, // 0018 JMP #001E
|
0x70020004, // 0018 JMP #001E
|
||||||
0x88180334, // 0019 GETMBR R6 R1 K52
|
0x88180334, // 0019 GETMBR R6 R1 K52
|
||||||
0x8C180D35, // 001A GETMET R6 R6 K53
|
0x8C180D35, // 001A GETMET R6 R6 K53
|
||||||
0x7C180200, // 001B CALL R6 1
|
0x7C180200, // 001B CALL R6 1
|
||||||
0x90121806, // 001C SETMBR R4 K12 R6
|
0x90121806, // 001C SETMBR R4 K12 R6
|
||||||
0x90123112, // 001D SETMBR R4 K24 K18
|
0x90123312, // 001D SETMBR R4 K25 K18
|
||||||
0x90124B0B, // 001E SETMBR R4 K37 K11
|
0x90124B0B, // 001E SETMBR R4 K37 K11
|
||||||
0x90124C02, // 001F SETMBR R4 K38 R2
|
0x90124C02, // 001F SETMBR R4 K38 R2
|
||||||
0x88180346, // 0020 GETMBR R6 R1 K70
|
0x88180346, // 0020 GETMBR R6 R1 K70
|
||||||
@ -1013,14 +1013,14 @@ be_local_closure(class_Matter_Frame_decode_payload, /* name */
|
|||||||
0x8C0C052C, // 000F GETMET R3 R2 K44
|
0x8C0C052C, // 000F GETMET R3 R2 K44
|
||||||
0x54160007, // 0010 LDINT R5 8
|
0x54160007, // 0010 LDINT R5 8
|
||||||
0x08140205, // 0011 MUL R5 R1 R5
|
0x08140205, // 0011 MUL R5 R1 R5
|
||||||
0x00140B17, // 0012 ADD R5 R5 K23
|
0x00140B18, // 0012 ADD R5 R5 K24
|
||||||
0x5818000B, // 0013 LDCONST R6 K11
|
0x5818000B, // 0013 LDCONST R6 K11
|
||||||
0x7C0C0600, // 0014 CALL R3 3
|
0x7C0C0600, // 0014 CALL R3 3
|
||||||
0x90028E03, // 0015 SETMBR R0 K71 R3
|
0x90028E03, // 0015 SETMBR R0 K71 R3
|
||||||
0x8C0C052C, // 0016 GETMET R3 R2 K44
|
0x8C0C052C, // 0016 GETMET R3 R2 K44
|
||||||
0x54160007, // 0017 LDINT R5 8
|
0x54160007, // 0017 LDINT R5 8
|
||||||
0x08140205, // 0018 MUL R5 R1 R5
|
0x08140205, // 0018 MUL R5 R1 R5
|
||||||
0x00140B19, // 0019 ADD R5 R5 K25
|
0x00140B1A, // 0019 ADD R5 R5 K26
|
||||||
0x5818000B, // 001A LDCONST R6 K11
|
0x5818000B, // 001A LDCONST R6 K11
|
||||||
0x7C0C0600, // 001B CALL R3 3
|
0x7C0C0600, // 001B CALL R3 3
|
||||||
0x90024603, // 001C SETMBR R0 K35 R3
|
0x90024603, // 001C SETMBR R0 K35 R3
|
||||||
@ -1043,8 +1043,8 @@ be_local_closure(class_Matter_Frame_decode_payload, /* name */
|
|||||||
0x7C0C0600, // 002D CALL R3 3
|
0x7C0C0600, // 002D CALL R3 3
|
||||||
0x90024C03, // 002E SETMBR R0 K38 R3
|
0x90024C03, // 002E SETMBR R0 K38 R3
|
||||||
0x8C0C052B, // 002F GETMET R3 R2 K43
|
0x8C0C052B, // 002F GETMET R3 R2 K43
|
||||||
0x00140319, // 0030 ADD R5 R1 K25
|
0x0014031A, // 0030 ADD R5 R1 K26
|
||||||
0x58180019, // 0031 LDCONST R6 K25
|
0x5818001A, // 0031 LDCONST R6 K26
|
||||||
0x7C0C0600, // 0032 CALL R3 3
|
0x7C0C0600, // 0032 CALL R3 3
|
||||||
0x90024E03, // 0033 SETMBR R0 K39 R3
|
0x90024E03, // 0033 SETMBR R0 K39 R3
|
||||||
0x880C0125, // 0034 GETMBR R3 R0 K37
|
0x880C0125, // 0034 GETMBR R3 R0 K37
|
||||||
@ -1056,7 +1056,7 @@ be_local_closure(class_Matter_Frame_decode_payload, /* name */
|
|||||||
0x8C0C052B, // 003A GETMET R3 R2 K43
|
0x8C0C052B, // 003A GETMET R3 R2 K43
|
||||||
0x54160003, // 003B LDINT R5 4
|
0x54160003, // 003B LDINT R5 4
|
||||||
0x00140205, // 003C ADD R5 R1 R5
|
0x00140205, // 003C ADD R5 R1 R5
|
||||||
0x58180019, // 003D LDCONST R6 K25
|
0x5818001A, // 003D LDCONST R6 K26
|
||||||
0x7C0C0600, // 003E CALL R3 3
|
0x7C0C0600, // 003E CALL R3 3
|
||||||
0x90025003, // 003F SETMBR R0 K40 R3
|
0x90025003, // 003F SETMBR R0 K40 R3
|
||||||
0x540E0005, // 0040 LDINT R3 6
|
0x540E0005, // 0040 LDINT R3 6
|
||||||
@ -1065,10 +1065,10 @@ be_local_closure(class_Matter_Frame_decode_payload, /* name */
|
|||||||
0x780E0005, // 0043 JMPF R3 #004A
|
0x780E0005, // 0043 JMPF R3 #004A
|
||||||
0x8C0C052B, // 0044 GETMET R3 R2 K43
|
0x8C0C052B, // 0044 GETMET R3 R2 K43
|
||||||
0x5C140200, // 0045 MOVE R5 R1
|
0x5C140200, // 0045 MOVE R5 R1
|
||||||
0x58180019, // 0046 LDCONST R6 K25
|
0x5818001A, // 0046 LDCONST R6 K26
|
||||||
0x7C0C0600, // 0047 CALL R3 3
|
0x7C0C0600, // 0047 CALL R3 3
|
||||||
0x90029003, // 0048 SETMBR R0 K72 R3
|
0x90029003, // 0048 SETMBR R0 K72 R3
|
||||||
0x00040319, // 0049 ADD R1 R1 K25
|
0x0004031A, // 0049 ADD R1 R1 K26
|
||||||
0x880C0124, // 004A GETMBR R3 R0 K36
|
0x880C0124, // 004A GETMBR R3 R0 K36
|
||||||
0x780E0006, // 004B JMPF R3 #0053
|
0x780E0006, // 004B JMPF R3 #0053
|
||||||
0x8C0C052B, // 004C GETMET R3 R2 K43
|
0x8C0C052B, // 004C GETMET R3 R2 K43
|
||||||
@ -1082,9 +1082,9 @@ be_local_closure(class_Matter_Frame_decode_payload, /* name */
|
|||||||
0x780E0005, // 0054 JMPF R3 #005B
|
0x780E0005, // 0054 JMPF R3 #005B
|
||||||
0x8C0C052B, // 0055 GETMET R3 R2 K43
|
0x8C0C052B, // 0055 GETMET R3 R2 K43
|
||||||
0x5C140200, // 0056 MOVE R5 R1
|
0x5C140200, // 0056 MOVE R5 R1
|
||||||
0x58180019, // 0057 LDCONST R6 K25
|
0x5818001A, // 0057 LDCONST R6 K26
|
||||||
0x7C0C0600, // 0058 CALL R3 3
|
0x7C0C0600, // 0058 CALL R3 3
|
||||||
0x00100719, // 0059 ADD R4 R3 K25
|
0x0010071A, // 0059 ADD R4 R3 K26
|
||||||
0x00040204, // 005A ADD R1 R1 R4
|
0x00040204, // 005A ADD R1 R1 R4
|
||||||
0x90025401, // 005B SETMBR R0 K42 R1
|
0x90025401, // 005B SETMBR R0 K42 R1
|
||||||
0x80040000, // 005C RET 1 R0
|
0x80040000, // 005C RET 1 R0
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Tasmota lib
|
* Tasmota lib
|
||||||
*
|
*
|
||||||
* To use: `import MI32`
|
* To use: `import MI32`
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
#include "be_constobj.h"
|
#include "be_constobj.h"
|
||||||
@ -25,6 +25,9 @@ BE_FUNC_CTYPE_DECLARE(be_MI32_set_hum, "", "ii");
|
|||||||
extern void be_MI32_set_temp(int slot, int temp_val);
|
extern void be_MI32_set_temp(int slot, int temp_val);
|
||||||
BE_FUNC_CTYPE_DECLARE(be_MI32_set_temp, "", "ii");
|
BE_FUNC_CTYPE_DECLARE(be_MI32_set_temp, "", "ii");
|
||||||
|
|
||||||
|
extern bbool be_MI32_widget(const char *sbuf, void* function);
|
||||||
|
BE_FUNC_CTYPE_DECLARE(be_MI32_widget, "b", "s[c]");
|
||||||
|
|
||||||
#include "be_fixed_MI32.h"
|
#include "be_fixed_MI32.h"
|
||||||
|
|
||||||
/* @const_object_info_begin
|
/* @const_object_info_begin
|
||||||
@ -35,12 +38,13 @@ module MI32 (scope: global) {
|
|||||||
set_bat, ctype_func(be_MI32_set_bat)
|
set_bat, ctype_func(be_MI32_set_bat)
|
||||||
set_hum, ctype_func(be_MI32_set_hum)
|
set_hum, ctype_func(be_MI32_set_hum)
|
||||||
set_temp, ctype_func(be_MI32_set_temp)
|
set_temp, ctype_func(be_MI32_set_temp)
|
||||||
|
widget, ctype_func(be_MI32_widget)
|
||||||
}
|
}
|
||||||
@const_object_info_end */
|
@const_object_info_end */
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Tasmota lib
|
* Tasmota lib
|
||||||
*
|
*
|
||||||
* To use: `import BLE`
|
* To use: `import BLE`
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
#include "be_constobj.h"
|
#include "be_constobj.h"
|
||||||
#include "be_mapping.h"
|
#include "be_mapping.h"
|
||||||
|
|
||||||
#if defined(USE_BERRY_ULP) && (defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3))
|
#if defined(USE_BERRY_ULP) && defined(CONFIG_ULP_COPROC_ENABLED)
|
||||||
|
|
||||||
extern void be_ULP_run(int32_t entry);
|
extern void be_ULP_run(int32_t entry);
|
||||||
BE_FUNC_CTYPE_DECLARE(be_ULP_run, "", "[i]");
|
BE_FUNC_CTYPE_DECLARE(be_ULP_run, "", "[i]");
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Tasmota LVGL lv_signal_bars widget
|
* Drivers for AXP192 and AXP202 I2C Solidified
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
#include "solidify/solidified_i2c_axp192.h"
|
#include "solidify/solidified_i2c_axp192.h"
|
||||||
#include "solidify/solidified_i2c_axp202.h"
|
#include "solidify/solidified_i2c_axp202.h"
|
||||||
|
|||||||
@ -7,7 +7,9 @@
|
|||||||
|
|
||||||
#ifdef USE_WS2812
|
#ifdef USE_WS2812
|
||||||
|
|
||||||
extern int be_neopixelbus_call_native(bvm *vm);
|
#include "TasmotaLED.h"
|
||||||
|
|
||||||
|
extern int be_tasmotaled_call_native(bvm *vm);
|
||||||
extern int be_leds_blend_color(bvm *vm);
|
extern int be_leds_blend_color(bvm *vm);
|
||||||
extern int be_leds_apply_bri_gamma(bvm *vm);
|
extern int be_leds_apply_bri_gamma(bvm *vm);
|
||||||
|
|
||||||
@ -16,10 +18,15 @@ class be_class_Leds_ntv (scope: global, name: Leds_ntv, strings: weak) {
|
|||||||
_p, var
|
_p, var
|
||||||
_t, var
|
_t, var
|
||||||
|
|
||||||
WS2812_GRB, int(1)
|
WS2812_GRB, int(ws2812_grb)
|
||||||
SK6812_GRBW, int(2)
|
SK6812_GRBW, int(sk6812_grbw)
|
||||||
|
SK6812_GRB, int(sk6812_grb)
|
||||||
|
|
||||||
call_native, func(be_neopixelbus_call_native)
|
RMT, int(TasmotaLed_RMT)
|
||||||
|
SPI, int(TasmotaLed_SPI)
|
||||||
|
I2S, int(TasmotaLed_I2S)
|
||||||
|
|
||||||
|
call_native, func(be_tasmotaled_call_native)
|
||||||
|
|
||||||
blend_color, static_func(be_leds_blend_color)
|
blend_color, static_func(be_leds_blend_color)
|
||||||
apply_bri_gamma, static_func(be_leds_apply_bri_gamma)
|
apply_bri_gamma, static_func(be_leds_apply_bri_gamma)
|
||||||
|
|||||||
@ -124,7 +124,7 @@ autoconf_module.init = def (m)
|
|||||||
# Displays a "Autoconf" button on the configuration page
|
# Displays a "Autoconf" button on the configuration page
|
||||||
def web_add_config_button()
|
def web_add_config_button()
|
||||||
import webserver
|
import webserver
|
||||||
webserver.content_send("<p><form id=ac action='ac' style='display: block;' method='get'><button>Auto-configuration</button></form></p>")
|
webserver.content_send("<p><form id=ac action='ac' style='display: block;' method='get'><button>Auto-Conf</button></form></p>")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -56,6 +56,15 @@ class I2C_Driver
|
|||||||
def write8(reg, val)
|
def write8(reg, val)
|
||||||
return self.wire.write(self.addr, reg, val, 1)
|
return self.wire.write(self.addr, reg, val, 1)
|
||||||
end
|
end
|
||||||
|
#- write register with 16 bits value -#
|
||||||
|
def write16(reg, val)
|
||||||
|
return self.wire.write(self.addr, reg, val, 2)
|
||||||
|
end
|
||||||
|
#- write register with 16 bits value, Little Endian -#
|
||||||
|
def write16LE(reg, val)
|
||||||
|
val = ((val & 0xFF) << 8) | ((val & 0xFF00) >> 8)
|
||||||
|
return self.write16(reg, val)
|
||||||
|
end
|
||||||
|
|
||||||
# Set or clear a specific bit in a register
|
# Set or clear a specific bit in a register
|
||||||
# write_bit(reg:int, bit:int, state:bool) -> nil
|
# write_bit(reg:int, bit:int, state:bool) -> nil
|
||||||
@ -94,6 +103,11 @@ class I2C_Driver
|
|||||||
var buf = self.wire.read_bytes(self.addr, reg, 2)
|
var buf = self.wire.read_bytes(self.addr, reg, 2)
|
||||||
return (buf[0] << 8) + buf[1]
|
return (buf[0] << 8) + buf[1]
|
||||||
end
|
end
|
||||||
|
# read 16 bits Little Endian
|
||||||
|
def read16LE(reg)
|
||||||
|
var buf = self.wire.read_bytes(self.addr, reg, 2)
|
||||||
|
return (buf[1] << 8) + buf[0]
|
||||||
|
end
|
||||||
# read 24 bits
|
# read 24 bits
|
||||||
def read24(reg)
|
def read24(reg)
|
||||||
var buf = self.wire.read_bytes(self.addr, reg, 3)
|
var buf = self.wire.read_bytes(self.addr, reg, 3)
|
||||||
|
|||||||
@ -31,8 +31,8 @@ class Leds : Leds_ntv
|
|||||||
# leds:int = number of leds of the strip
|
# leds:int = number of leds of the strip
|
||||||
# gpio:int (optional) = GPIO for NeoPixel. If not specified, takes the WS2812 gpio
|
# gpio:int (optional) = GPIO for NeoPixel. If not specified, takes the WS2812 gpio
|
||||||
# typ:int (optional) = Type of LED, defaults to WS2812 RGB
|
# typ:int (optional) = Type of LED, defaults to WS2812 RGB
|
||||||
# rmt:int (optional) = RMT hardware channel to use, leave default unless you have a good reason
|
# hardware:int (optional) = hardware support (Leds.RMT, Leds.SPI)
|
||||||
def init(leds, gpio_phy, typ, rmt) # rmt is optional
|
def init(leds, gpio_phy, typ, hardware)
|
||||||
import gpio
|
import gpio
|
||||||
self.gamma = true # gamma is enabled by default, it should be disabled explicitly if needed
|
self.gamma = true # gamma is enabled by default, it should be disabled explicitly if needed
|
||||||
if (gpio_phy == nil) || (gpio_phy == gpio.pin(gpio.WS2812, 0))
|
if (gpio_phy == nil) || (gpio_phy == gpio.pin(gpio.WS2812, 0))
|
||||||
@ -47,7 +47,7 @@ class Leds : Leds_ntv
|
|||||||
self.bri = 127 # 50% brightness by default
|
self.bri = 127 # 50% brightness by default
|
||||||
|
|
||||||
# initialize the structure
|
# initialize the structure
|
||||||
self.ctor(self.leds, gpio_phy, typ, rmt)
|
self.ctor(self.leds, gpio_phy, typ, hardware)
|
||||||
end
|
end
|
||||||
|
|
||||||
if self._p == nil raise "internal_error", "couldn't not initialize noepixelbus" end
|
if self._p == nil raise "internal_error", "couldn't not initialize noepixelbus" end
|
||||||
@ -56,44 +56,6 @@ class Leds : Leds_ntv
|
|||||||
self.begin()
|
self.begin()
|
||||||
end
|
end
|
||||||
|
|
||||||
# assign RMT
|
|
||||||
static def assign_rmt(gpio_phy)
|
|
||||||
gpio_phy = int(gpio_phy)
|
|
||||||
if gpio_phy < 0 raise "value_error", "invalid GPIO number" end
|
|
||||||
|
|
||||||
import global
|
|
||||||
var rmt
|
|
||||||
# if "_rmt" is not initialized, set to an array of GPIO of size MAX_RMT
|
|
||||||
if !global.contains("_rmt")
|
|
||||||
rmt = []
|
|
||||||
global._rmt = rmt
|
|
||||||
for i:0..gpio.MAX_RMT-1
|
|
||||||
rmt.push(-1)
|
|
||||||
end
|
|
||||||
# if default WS2812 is set, assign RMT0
|
|
||||||
if gpio.pin_used(gpio.WS2812, 0)
|
|
||||||
rmt[0] = gpio.pin(gpio.WS2812, 0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
rmt = global._rmt
|
|
||||||
# find an already assigned slot or try to assign a new one
|
|
||||||
var i = 0
|
|
||||||
var first_free = -1
|
|
||||||
while i < gpio.MAX_RMT
|
|
||||||
var elt = rmt[i]
|
|
||||||
if elt == gpio_phy return i end # already assigned
|
|
||||||
if elt < 0 && first_free < 0 first_free = i end # found a free slot
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
if first_free >= 0
|
|
||||||
rmt[first_free] = gpio_phy
|
|
||||||
return first_free
|
|
||||||
end
|
|
||||||
# no more slot
|
|
||||||
raise "internal_error", "no more RMT channel available"
|
|
||||||
end
|
|
||||||
|
|
||||||
def clear()
|
def clear()
|
||||||
self.clear_to(0x000000)
|
self.clear_to(0x000000)
|
||||||
self.show()
|
self.show()
|
||||||
@ -109,17 +71,14 @@ class Leds : Leds_ntv
|
|||||||
return self.bri
|
return self.bri
|
||||||
end
|
end
|
||||||
|
|
||||||
def ctor(leds, gpio_phy, typ, rmt)
|
def ctor(leds, gpio_phy, typ, hardware)
|
||||||
if gpio_phy == nil
|
if gpio_phy == nil
|
||||||
self.call_native(0) # native driver
|
self.call_native(0) # native driver
|
||||||
else
|
else
|
||||||
if typ == nil
|
if typ == nil
|
||||||
typ = self.WS2812_GRB
|
typ = self.WS2812_GRB
|
||||||
end
|
end
|
||||||
if rmt == nil
|
self.call_native(0, leds, gpio_phy, typ, hardware)
|
||||||
rmt = self.assign_rmt(gpio_phy)
|
|
||||||
end
|
|
||||||
self.call_native(0, leds, gpio_phy, typ, rmt)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
def begin()
|
def begin()
|
||||||
@ -155,9 +114,13 @@ class Leds : Leds_ntv
|
|||||||
def pixel_offset()
|
def pixel_offset()
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
def clear_to(col, bri)
|
def clear_to(col, bri, index, len)
|
||||||
if (bri == nil) bri = self.bri end
|
if (bri == nil) bri = self.bri end
|
||||||
self.call_native(9, self.to_gamma(col, bri))
|
if index != nil && len != nil
|
||||||
|
self.call_native(9, self.to_gamma(col, bri), index, len)
|
||||||
|
else
|
||||||
|
self.call_native(9, self.to_gamma(col, bri))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
def set_pixel_color(idx, col, bri)
|
def set_pixel_color(idx, col, bri)
|
||||||
if (bri == nil) bri = self.bri end
|
if (bri == nil) bri = self.bri end
|
||||||
@ -403,15 +366,15 @@ anim()
|
|||||||
|
|
||||||
#-
|
#-
|
||||||
|
|
||||||
var s = Leds_matrix(5, 5, gpio.pin(gpio.WS2812, 1))
|
var s = Leds(25, gpio.pin(gpio.WS2812, 1)).create_matrix(5, 5)
|
||||||
s.set_alternate(true)
|
s.set_alternate(true)
|
||||||
s.clear_to(0x300000)
|
s.clear_to(0x400000)
|
||||||
s.show()
|
s.show()
|
||||||
x = 0
|
x = 0
|
||||||
y = 0
|
y = 0
|
||||||
|
|
||||||
def anim()
|
def anim()
|
||||||
s.clear_to(0x300000)
|
s.clear_to(0x400000)
|
||||||
s.set_matrix_pixel_color(x, y, 0x004000)
|
s.set_matrix_pixel_color(x, y, 0x004000)
|
||||||
s.show()
|
s.show()
|
||||||
y = (y + 1) % 5
|
y = (y + 1) % 5
|
||||||
|
|||||||
@ -121,7 +121,7 @@ static const bvalue be_ktab_class_Autoconf[126] = {
|
|||||||
/* K113 */ be_nested_str(CFG_X3A_X20loaded_X20_X27_X25s_X27),
|
/* K113 */ be_nested_str(CFG_X3A_X20loaded_X20_X27_X25s_X27),
|
||||||
/* K114 */ be_nested_str(files),
|
/* K114 */ be_nested_str(files),
|
||||||
/* K115 */ be_nested_str(CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27),
|
/* K115 */ be_nested_str(CFG_X3A_X20exception_X20_X27_X25s_X27_X20_X2D_X20_X27_X25s_X27),
|
||||||
/* K116 */ be_nested_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E),
|
/* K116 */ be_nested_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2DConf_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E),
|
||||||
/* K117 */ be_nested_str(add_driver),
|
/* K117 */ be_nested_str(add_driver),
|
||||||
/* K118 */ be_nested_str(CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29),
|
/* K118 */ be_nested_str(CFG_X3A_X20multiple_X20autoconf_X20files_X20found_X2C_X20aborting_X20_X28_X27_X25s_X27_X20_X2B_X20_X27_X25s_X27_X29),
|
||||||
/* K119 */ be_nested_str(CFG_X3A_X20No_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found),
|
/* K119 */ be_nested_str(CFG_X3A_X20No_X20_X27_X2A_X2Eautoconf_X27_X20file_X20found),
|
||||||
|
|||||||
@ -3,81 +3,33 @@
|
|||||||
* Generated code, don't edit *
|
* Generated code, don't edit *
|
||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
#include "be_constobj.h"
|
#include "be_constobj.h"
|
||||||
// compact class 'I2C_Driver' ktab size: 19, total: 60 (saved 328 bytes)
|
// compact class 'I2C_Driver' ktab size: 20, total: 71 (saved 408 bytes)
|
||||||
static const bvalue be_ktab_class_I2C_Driver[19] = {
|
static const bvalue be_ktab_class_I2C_Driver[20] = {
|
||||||
/* K0 */ be_const_int(0),
|
/* K0 */ be_nested_str(wire),
|
||||||
/* K1 */ be_const_int(1),
|
/* K1 */ be_nested_str(read_bytes),
|
||||||
/* K2 */ be_nested_str(write8),
|
/* K2 */ be_nested_str(addr),
|
||||||
/* K3 */ be_nested_str(read8),
|
/* K3 */ be_const_int(0),
|
||||||
/* K4 */ be_nested_str(wire),
|
/* K4 */ be_const_int(1),
|
||||||
/* K5 */ be_nested_str(read_bytes),
|
/* K5 */ be_const_int(2),
|
||||||
/* K6 */ be_nested_str(addr),
|
/* K6 */ be_const_int(3),
|
||||||
/* K7 */ be_const_int(2),
|
/* K7 */ be_nested_str(tasmota),
|
||||||
/* K8 */ be_const_int(3),
|
/* K8 */ be_nested_str(i2c_enabled),
|
||||||
/* K9 */ be_nested_str(tasmota),
|
/* K9 */ be_nested_str(wire_scan),
|
||||||
/* K10 */ be_nested_str(i2c_enabled),
|
/* K10 */ be_nested_str(function),
|
||||||
/* K11 */ be_nested_str(wire_scan),
|
/* K11 */ be_nested_str(name),
|
||||||
/* K12 */ be_nested_str(function),
|
/* K12 */ be_nested_str(I2C_X3A),
|
||||||
/* K13 */ be_nested_str(name),
|
/* K13 */ be_nested_str(detected_X20on_X20bus),
|
||||||
/* K14 */ be_nested_str(I2C_X3A),
|
/* K14 */ be_nested_str(bus),
|
||||||
/* K15 */ be_nested_str(detected_X20on_X20bus),
|
/* K15 */ be_nested_str(write8),
|
||||||
/* K16 */ be_nested_str(bus),
|
/* K16 */ be_nested_str(read8),
|
||||||
/* K17 */ be_nested_str(write),
|
/* K17 */ be_nested_str(write16),
|
||||||
/* K18 */ be_nested_str(read),
|
/* K18 */ be_nested_str(read),
|
||||||
|
/* K19 */ be_nested_str(write),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern const bclass be_class_I2C_Driver;
|
extern const bclass be_class_I2C_Driver;
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
** Solidified function: write_bit
|
|
||||||
********************************************************************/
|
|
||||||
be_local_closure(class_I2C_Driver_write_bit, /* name */
|
|
||||||
be_nested_proto(
|
|
||||||
11, /* nstack */
|
|
||||||
4, /* argc */
|
|
||||||
10, /* varg */
|
|
||||||
0, /* has upvals */
|
|
||||||
NULL, /* no upvals */
|
|
||||||
0, /* has sup protos */
|
|
||||||
NULL, /* no sub protos */
|
|
||||||
1, /* has constants */
|
|
||||||
&be_ktab_class_I2C_Driver, /* shared constants */
|
|
||||||
&be_const_str_write_bit,
|
|
||||||
&be_const_str_solidified,
|
|
||||||
( &(const binstruction[26]) { /* code */
|
|
||||||
0x14100500, // 0000 LT R4 R2 K0
|
|
||||||
0x74120002, // 0001 JMPT R4 #0005
|
|
||||||
0x54120006, // 0002 LDINT R4 7
|
|
||||||
0x24100404, // 0003 GT R4 R2 R4
|
|
||||||
0x78120000, // 0004 JMPF R4 #0006
|
|
||||||
0x80000800, // 0005 RET 0
|
|
||||||
0x38120202, // 0006 SHL R4 K1 R2
|
|
||||||
0x780E0007, // 0007 JMPF R3 #0010
|
|
||||||
0x8C140102, // 0008 GETMET R5 R0 K2
|
|
||||||
0x5C1C0200, // 0009 MOVE R7 R1
|
|
||||||
0x8C200103, // 000A GETMET R8 R0 K3
|
|
||||||
0x5C280200, // 000B MOVE R10 R1
|
|
||||||
0x7C200400, // 000C CALL R8 2
|
|
||||||
0x30201004, // 000D OR R8 R8 R4
|
|
||||||
0x7C140600, // 000E CALL R5 3
|
|
||||||
0x70020008, // 000F JMP #0019
|
|
||||||
0x8C140102, // 0010 GETMET R5 R0 K2
|
|
||||||
0x5C1C0200, // 0011 MOVE R7 R1
|
|
||||||
0x8C200103, // 0012 GETMET R8 R0 K3
|
|
||||||
0x5C280200, // 0013 MOVE R10 R1
|
|
||||||
0x7C200400, // 0014 CALL R8 2
|
|
||||||
0x542600FE, // 0015 LDINT R9 255
|
|
||||||
0x04241204, // 0016 SUB R9 R9 R4
|
|
||||||
0x2C201009, // 0017 AND R8 R8 R9
|
|
||||||
0x7C140600, // 0018 CALL R5 3
|
|
||||||
0x80000000, // 0019 RET 0
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
/*******************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Solidified function: read32
|
** Solidified function: read32
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
@ -95,24 +47,24 @@ be_local_closure(class_I2C_Driver_read32, /* name */
|
|||||||
&be_const_str_read32,
|
&be_const_str_read32,
|
||||||
&be_const_str_solidified,
|
&be_const_str_solidified,
|
||||||
( &(const binstruction[20]) { /* code */
|
( &(const binstruction[20]) { /* code */
|
||||||
0x88080104, // 0000 GETMBR R2 R0 K4
|
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||||
0x8C080505, // 0001 GETMET R2 R2 K5
|
0x8C080501, // 0001 GETMET R2 R2 K1
|
||||||
0x88100106, // 0002 GETMBR R4 R0 K6
|
0x88100102, // 0002 GETMBR R4 R0 K2
|
||||||
0x5C140200, // 0003 MOVE R5 R1
|
0x5C140200, // 0003 MOVE R5 R1
|
||||||
0x541A0003, // 0004 LDINT R6 4
|
0x541A0003, // 0004 LDINT R6 4
|
||||||
0x7C080800, // 0005 CALL R2 4
|
0x7C080800, // 0005 CALL R2 4
|
||||||
0x940C0500, // 0006 GETIDX R3 R2 K0
|
0x940C0503, // 0006 GETIDX R3 R2 K3
|
||||||
0x54120017, // 0007 LDINT R4 24
|
0x54120017, // 0007 LDINT R4 24
|
||||||
0x380C0604, // 0008 SHL R3 R3 R4
|
0x380C0604, // 0008 SHL R3 R3 R4
|
||||||
0x94100501, // 0009 GETIDX R4 R2 K1
|
0x94100504, // 0009 GETIDX R4 R2 K4
|
||||||
0x5416000F, // 000A LDINT R5 16
|
0x5416000F, // 000A LDINT R5 16
|
||||||
0x38100805, // 000B SHL R4 R4 R5
|
0x38100805, // 000B SHL R4 R4 R5
|
||||||
0x000C0604, // 000C ADD R3 R3 R4
|
0x000C0604, // 000C ADD R3 R3 R4
|
||||||
0x94100507, // 000D GETIDX R4 R2 K7
|
0x94100505, // 000D GETIDX R4 R2 K5
|
||||||
0x54160007, // 000E LDINT R5 8
|
0x54160007, // 000E LDINT R5 8
|
||||||
0x38100805, // 000F SHL R4 R4 R5
|
0x38100805, // 000F SHL R4 R4 R5
|
||||||
0x000C0604, // 0010 ADD R3 R3 R4
|
0x000C0604, // 0010 ADD R3 R3 R4
|
||||||
0x94100508, // 0011 GETIDX R4 R2 K8
|
0x94100506, // 0011 GETIDX R4 R2 K6
|
||||||
0x000C0604, // 0012 ADD R3 R3 R4
|
0x000C0604, // 0012 ADD R3 R3 R4
|
||||||
0x80040600, // 0013 RET 1 R3
|
0x80040600, // 0013 RET 1 R3
|
||||||
})
|
})
|
||||||
@ -121,115 +73,6 @@ be_local_closure(class_I2C_Driver_read32, /* name */
|
|||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
** Solidified function: read13
|
|
||||||
********************************************************************/
|
|
||||||
be_local_closure(class_I2C_Driver_read13, /* name */
|
|
||||||
be_nested_proto(
|
|
||||||
7, /* nstack */
|
|
||||||
2, /* argc */
|
|
||||||
10, /* varg */
|
|
||||||
0, /* has upvals */
|
|
||||||
NULL, /* no upvals */
|
|
||||||
0, /* has sup protos */
|
|
||||||
NULL, /* no sub protos */
|
|
||||||
1, /* has constants */
|
|
||||||
&be_ktab_class_I2C_Driver, /* shared constants */
|
|
||||||
&be_const_str_read13,
|
|
||||||
&be_const_str_solidified,
|
|
||||||
( &(const binstruction[12]) { /* code */
|
|
||||||
0x88080104, // 0000 GETMBR R2 R0 K4
|
|
||||||
0x8C080505, // 0001 GETMET R2 R2 K5
|
|
||||||
0x88100106, // 0002 GETMBR R4 R0 K6
|
|
||||||
0x5C140200, // 0003 MOVE R5 R1
|
|
||||||
0x58180007, // 0004 LDCONST R6 K7
|
|
||||||
0x7C080800, // 0005 CALL R2 4
|
|
||||||
0x940C0500, // 0006 GETIDX R3 R2 K0
|
|
||||||
0x54120004, // 0007 LDINT R4 5
|
|
||||||
0x380C0604, // 0008 SHL R3 R3 R4
|
|
||||||
0x94100501, // 0009 GETIDX R4 R2 K1
|
|
||||||
0x000C0604, // 000A ADD R3 R3 R4
|
|
||||||
0x80040600, // 000B RET 1 R3
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
/*******************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
** Solidified function: read24
|
|
||||||
********************************************************************/
|
|
||||||
be_local_closure(class_I2C_Driver_read24, /* name */
|
|
||||||
be_nested_proto(
|
|
||||||
7, /* nstack */
|
|
||||||
2, /* argc */
|
|
||||||
10, /* varg */
|
|
||||||
0, /* has upvals */
|
|
||||||
NULL, /* no upvals */
|
|
||||||
0, /* has sup protos */
|
|
||||||
NULL, /* no sub protos */
|
|
||||||
1, /* has constants */
|
|
||||||
&be_ktab_class_I2C_Driver, /* shared constants */
|
|
||||||
&be_const_str_read24,
|
|
||||||
&be_const_str_solidified,
|
|
||||||
( &(const binstruction[16]) { /* code */
|
|
||||||
0x88080104, // 0000 GETMBR R2 R0 K4
|
|
||||||
0x8C080505, // 0001 GETMET R2 R2 K5
|
|
||||||
0x88100106, // 0002 GETMBR R4 R0 K6
|
|
||||||
0x5C140200, // 0003 MOVE R5 R1
|
|
||||||
0x58180008, // 0004 LDCONST R6 K8
|
|
||||||
0x7C080800, // 0005 CALL R2 4
|
|
||||||
0x940C0500, // 0006 GETIDX R3 R2 K0
|
|
||||||
0x5412000F, // 0007 LDINT R4 16
|
|
||||||
0x380C0604, // 0008 SHL R3 R3 R4
|
|
||||||
0x94100501, // 0009 GETIDX R4 R2 K1
|
|
||||||
0x54160007, // 000A LDINT R5 8
|
|
||||||
0x38100805, // 000B SHL R4 R4 R5
|
|
||||||
0x000C0604, // 000C ADD R3 R3 R4
|
|
||||||
0x94100507, // 000D GETIDX R4 R2 K7
|
|
||||||
0x000C0604, // 000E ADD R3 R3 R4
|
|
||||||
0x80040600, // 000F RET 1 R3
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
/*******************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
** Solidified function: read14
|
|
||||||
********************************************************************/
|
|
||||||
be_local_closure(class_I2C_Driver_read14, /* name */
|
|
||||||
be_nested_proto(
|
|
||||||
7, /* nstack */
|
|
||||||
2, /* argc */
|
|
||||||
10, /* varg */
|
|
||||||
0, /* has upvals */
|
|
||||||
NULL, /* no upvals */
|
|
||||||
0, /* has sup protos */
|
|
||||||
NULL, /* no sub protos */
|
|
||||||
1, /* has constants */
|
|
||||||
&be_ktab_class_I2C_Driver, /* shared constants */
|
|
||||||
&be_const_str_read14,
|
|
||||||
&be_const_str_solidified,
|
|
||||||
( &(const binstruction[12]) { /* code */
|
|
||||||
0x88080104, // 0000 GETMBR R2 R0 K4
|
|
||||||
0x8C080505, // 0001 GETMET R2 R2 K5
|
|
||||||
0x88100106, // 0002 GETMBR R4 R0 K6
|
|
||||||
0x5C140200, // 0003 MOVE R5 R1
|
|
||||||
0x58180007, // 0004 LDCONST R6 K7
|
|
||||||
0x7C080800, // 0005 CALL R2 4
|
|
||||||
0x940C0500, // 0006 GETIDX R3 R2 K0
|
|
||||||
0x54120005, // 0007 LDINT R4 6
|
|
||||||
0x380C0604, // 0008 SHL R3 R3 R4
|
|
||||||
0x94100501, // 0009 GETIDX R4 R2 K1
|
|
||||||
0x000C0604, // 000A ADD R3 R3 R4
|
|
||||||
0x80040600, // 000B RET 1 R3
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
/*******************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Solidified function: init
|
** Solidified function: init
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
@ -250,45 +93,45 @@ be_local_closure(class_I2C_Driver_init, /* name */
|
|||||||
0x4C100000, // 0000 LDNIL R4
|
0x4C100000, // 0000 LDNIL R4
|
||||||
0x20100604, // 0001 NE R4 R3 R4
|
0x20100604, // 0001 NE R4 R3 R4
|
||||||
0x78120005, // 0002 JMPF R4 #0009
|
0x78120005, // 0002 JMPF R4 #0009
|
||||||
0xB8121200, // 0003 GETNGBL R4 K9
|
0xB8120E00, // 0003 GETNGBL R4 K7
|
||||||
0x8C10090A, // 0004 GETMET R4 R4 K10
|
0x8C100908, // 0004 GETMET R4 R4 K8
|
||||||
0x5C180600, // 0005 MOVE R6 R3
|
0x5C180600, // 0005 MOVE R6 R3
|
||||||
0x7C100400, // 0006 CALL R4 2
|
0x7C100400, // 0006 CALL R4 2
|
||||||
0x74120000, // 0007 JMPT R4 #0009
|
0x74120000, // 0007 JMPT R4 #0009
|
||||||
0x80000800, // 0008 RET 0
|
0x80000800, // 0008 RET 0
|
||||||
0x90020C02, // 0009 SETMBR R0 K6 R2
|
0x90020402, // 0009 SETMBR R0 K2 R2
|
||||||
0xB8121200, // 000A GETNGBL R4 K9
|
0xB8120E00, // 000A GETNGBL R4 K7
|
||||||
0x8C10090B, // 000B GETMET R4 R4 K11
|
0x8C100909, // 000B GETMET R4 R4 K9
|
||||||
0x88180106, // 000C GETMBR R6 R0 K6
|
0x88180102, // 000C GETMBR R6 R0 K2
|
||||||
0x7C100400, // 000D CALL R4 2
|
0x7C100400, // 000D CALL R4 2
|
||||||
0x90020804, // 000E SETMBR R0 K4 R4
|
0x90020004, // 000E SETMBR R0 K0 R4
|
||||||
0x88100104, // 000F GETMBR R4 R0 K4
|
0x88100100, // 000F GETMBR R4 R0 K0
|
||||||
0x78120019, // 0010 JMPF R4 #002B
|
0x78120019, // 0010 JMPF R4 #002B
|
||||||
0x60100004, // 0011 GETGBL R4 G4
|
0x60100004, // 0011 GETGBL R4 G4
|
||||||
0x5C140200, // 0012 MOVE R5 R1
|
0x5C140200, // 0012 MOVE R5 R1
|
||||||
0x7C100200, // 0013 CALL R4 1
|
0x7C100200, // 0013 CALL R4 1
|
||||||
0x1C10090C, // 0014 EQ R4 R4 K12
|
0x1C10090A, // 0014 EQ R4 R4 K10
|
||||||
0x78120004, // 0015 JMPF R4 #001B
|
0x78120004, // 0015 JMPF R4 #001B
|
||||||
0x5C100200, // 0016 MOVE R4 R1
|
0x5C100200, // 0016 MOVE R4 R1
|
||||||
0x5C140000, // 0017 MOVE R5 R0
|
0x5C140000, // 0017 MOVE R5 R0
|
||||||
0x7C100200, // 0018 CALL R4 1
|
0x7C100200, // 0018 CALL R4 1
|
||||||
0x90021A04, // 0019 SETMBR R0 K13 R4
|
0x90021604, // 0019 SETMBR R0 K11 R4
|
||||||
0x70020000, // 001A JMP #001C
|
0x70020000, // 001A JMP #001C
|
||||||
0x90021A01, // 001B SETMBR R0 K13 R1
|
0x90021601, // 001B SETMBR R0 K11 R1
|
||||||
0x8810010D, // 001C GETMBR R4 R0 K13
|
0x8810010B, // 001C GETMBR R4 R0 K11
|
||||||
0x4C140000, // 001D LDNIL R5
|
0x4C140000, // 001D LDNIL R5
|
||||||
0x1C100805, // 001E EQ R4 R4 R5
|
0x1C100805, // 001E EQ R4 R4 R5
|
||||||
0x78120001, // 001F JMPF R4 #0022
|
0x78120001, // 001F JMPF R4 #0022
|
||||||
0x4C100000, // 0020 LDNIL R4
|
0x4C100000, // 0020 LDNIL R4
|
||||||
0x90020804, // 0021 SETMBR R0 K4 R4
|
0x90020004, // 0021 SETMBR R0 K0 R4
|
||||||
0x88100104, // 0022 GETMBR R4 R0 K4
|
0x88100100, // 0022 GETMBR R4 R0 K0
|
||||||
0x78120006, // 0023 JMPF R4 #002B
|
0x78120006, // 0023 JMPF R4 #002B
|
||||||
0x60100001, // 0024 GETGBL R4 G1
|
0x60100001, // 0024 GETGBL R4 G1
|
||||||
0x5814000E, // 0025 LDCONST R5 K14
|
0x5814000C, // 0025 LDCONST R5 K12
|
||||||
0x8818010D, // 0026 GETMBR R6 R0 K13
|
0x8818010B, // 0026 GETMBR R6 R0 K11
|
||||||
0x581C000F, // 0027 LDCONST R7 K15
|
0x581C000D, // 0027 LDCONST R7 K13
|
||||||
0x88200104, // 0028 GETMBR R8 R0 K4
|
0x88200100, // 0028 GETMBR R8 R0 K0
|
||||||
0x88201110, // 0029 GETMBR R8 R8 K16
|
0x8820110E, // 0029 GETMBR R8 R8 K14
|
||||||
0x7C100800, // 002A CALL R4 4
|
0x7C100800, // 002A CALL R4 4
|
||||||
0x80000000, // 002B RET 0
|
0x80000000, // 002B RET 0
|
||||||
})
|
})
|
||||||
@ -298,11 +141,99 @@ be_local_closure(class_I2C_Driver_init, /* name */
|
|||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Solidified function: write8
|
** Solidified function: read24
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
be_local_closure(class_I2C_Driver_write8, /* name */
|
be_local_closure(class_I2C_Driver_read24, /* name */
|
||||||
be_nested_proto(
|
be_nested_proto(
|
||||||
9, /* nstack */
|
7, /* nstack */
|
||||||
|
2, /* argc */
|
||||||
|
10, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
&be_ktab_class_I2C_Driver, /* shared constants */
|
||||||
|
&be_const_str_read24,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[16]) { /* code */
|
||||||
|
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||||
|
0x8C080501, // 0001 GETMET R2 R2 K1
|
||||||
|
0x88100102, // 0002 GETMBR R4 R0 K2
|
||||||
|
0x5C140200, // 0003 MOVE R5 R1
|
||||||
|
0x58180006, // 0004 LDCONST R6 K6
|
||||||
|
0x7C080800, // 0005 CALL R2 4
|
||||||
|
0x940C0503, // 0006 GETIDX R3 R2 K3
|
||||||
|
0x5412000F, // 0007 LDINT R4 16
|
||||||
|
0x380C0604, // 0008 SHL R3 R3 R4
|
||||||
|
0x94100504, // 0009 GETIDX R4 R2 K4
|
||||||
|
0x54160007, // 000A LDINT R5 8
|
||||||
|
0x38100805, // 000B SHL R4 R4 R5
|
||||||
|
0x000C0604, // 000C ADD R3 R3 R4
|
||||||
|
0x94100505, // 000D GETIDX R4 R2 K5
|
||||||
|
0x000C0604, // 000E ADD R3 R3 R4
|
||||||
|
0x80040600, // 000F RET 1 R3
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: write_bit
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(class_I2C_Driver_write_bit, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
11, /* nstack */
|
||||||
|
4, /* argc */
|
||||||
|
10, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
&be_ktab_class_I2C_Driver, /* shared constants */
|
||||||
|
&be_const_str_write_bit,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[26]) { /* code */
|
||||||
|
0x14100503, // 0000 LT R4 R2 K3
|
||||||
|
0x74120002, // 0001 JMPT R4 #0005
|
||||||
|
0x54120006, // 0002 LDINT R4 7
|
||||||
|
0x24100404, // 0003 GT R4 R2 R4
|
||||||
|
0x78120000, // 0004 JMPF R4 #0006
|
||||||
|
0x80000800, // 0005 RET 0
|
||||||
|
0x38120802, // 0006 SHL R4 K4 R2
|
||||||
|
0x780E0007, // 0007 JMPF R3 #0010
|
||||||
|
0x8C14010F, // 0008 GETMET R5 R0 K15
|
||||||
|
0x5C1C0200, // 0009 MOVE R7 R1
|
||||||
|
0x8C200110, // 000A GETMET R8 R0 K16
|
||||||
|
0x5C280200, // 000B MOVE R10 R1
|
||||||
|
0x7C200400, // 000C CALL R8 2
|
||||||
|
0x30201004, // 000D OR R8 R8 R4
|
||||||
|
0x7C140600, // 000E CALL R5 3
|
||||||
|
0x70020008, // 000F JMP #0019
|
||||||
|
0x8C14010F, // 0010 GETMET R5 R0 K15
|
||||||
|
0x5C1C0200, // 0011 MOVE R7 R1
|
||||||
|
0x8C200110, // 0012 GETMET R8 R0 K16
|
||||||
|
0x5C280200, // 0013 MOVE R10 R1
|
||||||
|
0x7C200400, // 0014 CALL R8 2
|
||||||
|
0x542600FE, // 0015 LDINT R9 255
|
||||||
|
0x04241204, // 0016 SUB R9 R9 R4
|
||||||
|
0x2C201009, // 0017 AND R8 R8 R9
|
||||||
|
0x7C140600, // 0018 CALL R5 3
|
||||||
|
0x80000000, // 0019 RET 0
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: write16LE
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(class_I2C_Driver_write16LE, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
7, /* nstack */
|
||||||
3, /* argc */
|
3, /* argc */
|
||||||
10, /* varg */
|
10, /* varg */
|
||||||
0, /* has upvals */
|
0, /* has upvals */
|
||||||
@ -311,17 +242,24 @@ be_local_closure(class_I2C_Driver_write8, /* name */
|
|||||||
NULL, /* no sub protos */
|
NULL, /* no sub protos */
|
||||||
1, /* has constants */
|
1, /* has constants */
|
||||||
&be_ktab_class_I2C_Driver, /* shared constants */
|
&be_ktab_class_I2C_Driver, /* shared constants */
|
||||||
&be_const_str_write8,
|
&be_const_str_write16LE,
|
||||||
&be_const_str_solidified,
|
&be_const_str_solidified,
|
||||||
( &(const binstruction[ 8]) { /* code */
|
( &(const binstruction[15]) { /* code */
|
||||||
0x880C0104, // 0000 GETMBR R3 R0 K4
|
0x540E00FE, // 0000 LDINT R3 255
|
||||||
0x8C0C0711, // 0001 GETMET R3 R3 K17
|
0x2C0C0403, // 0001 AND R3 R2 R3
|
||||||
0x88140106, // 0002 GETMBR R5 R0 K6
|
0x54120007, // 0002 LDINT R4 8
|
||||||
0x5C180200, // 0003 MOVE R6 R1
|
0x380C0604, // 0003 SHL R3 R3 R4
|
||||||
0x5C1C0400, // 0004 MOVE R7 R2
|
0x5412FEFF, // 0004 LDINT R4 65280
|
||||||
0x58200001, // 0005 LDCONST R8 K1
|
0x2C100404, // 0005 AND R4 R2 R4
|
||||||
0x7C0C0A00, // 0006 CALL R3 5
|
0x54160007, // 0006 LDINT R5 8
|
||||||
0x80040600, // 0007 RET 1 R3
|
0x3C100805, // 0007 SHR R4 R4 R5
|
||||||
|
0x300C0604, // 0008 OR R3 R3 R4
|
||||||
|
0x5C080600, // 0009 MOVE R2 R3
|
||||||
|
0x8C0C0111, // 000A GETMET R3 R0 K17
|
||||||
|
0x5C140200, // 000B MOVE R5 R1
|
||||||
|
0x5C180400, // 000C MOVE R6 R2
|
||||||
|
0x7C0C0600, // 000D CALL R3 3
|
||||||
|
0x80040600, // 000E RET 1 R3
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -345,11 +283,11 @@ be_local_closure(class_I2C_Driver_read8, /* name */
|
|||||||
&be_const_str_read8,
|
&be_const_str_read8,
|
||||||
&be_const_str_solidified,
|
&be_const_str_solidified,
|
||||||
( &(const binstruction[ 7]) { /* code */
|
( &(const binstruction[ 7]) { /* code */
|
||||||
0x88080104, // 0000 GETMBR R2 R0 K4
|
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||||
0x8C080512, // 0001 GETMET R2 R2 K18
|
0x8C080512, // 0001 GETMET R2 R2 K18
|
||||||
0x88100106, // 0002 GETMBR R4 R0 K6
|
0x88100102, // 0002 GETMBR R4 R0 K2
|
||||||
0x5C140200, // 0003 MOVE R5 R1
|
0x5C140200, // 0003 MOVE R5 R1
|
||||||
0x58180001, // 0004 LDCONST R6 K1
|
0x58180004, // 0004 LDCONST R6 K4
|
||||||
0x7C080800, // 0005 CALL R2 4
|
0x7C080800, // 0005 CALL R2 4
|
||||||
0x80040400, // 0006 RET 1 R2
|
0x80040400, // 0006 RET 1 R2
|
||||||
})
|
})
|
||||||
@ -358,6 +296,76 @@ be_local_closure(class_I2C_Driver_read8, /* name */
|
|||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: read14
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(class_I2C_Driver_read14, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
7, /* nstack */
|
||||||
|
2, /* argc */
|
||||||
|
10, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
&be_ktab_class_I2C_Driver, /* shared constants */
|
||||||
|
&be_const_str_read14,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[12]) { /* code */
|
||||||
|
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||||
|
0x8C080501, // 0001 GETMET R2 R2 K1
|
||||||
|
0x88100102, // 0002 GETMBR R4 R0 K2
|
||||||
|
0x5C140200, // 0003 MOVE R5 R1
|
||||||
|
0x58180005, // 0004 LDCONST R6 K5
|
||||||
|
0x7C080800, // 0005 CALL R2 4
|
||||||
|
0x940C0503, // 0006 GETIDX R3 R2 K3
|
||||||
|
0x54120005, // 0007 LDINT R4 6
|
||||||
|
0x380C0604, // 0008 SHL R3 R3 R4
|
||||||
|
0x94100504, // 0009 GETIDX R4 R2 K4
|
||||||
|
0x000C0604, // 000A ADD R3 R3 R4
|
||||||
|
0x80040600, // 000B RET 1 R3
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: read16LE
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(class_I2C_Driver_read16LE, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
7, /* nstack */
|
||||||
|
2, /* argc */
|
||||||
|
10, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
&be_ktab_class_I2C_Driver, /* shared constants */
|
||||||
|
&be_const_str_read16LE,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[12]) { /* code */
|
||||||
|
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||||
|
0x8C080501, // 0001 GETMET R2 R2 K1
|
||||||
|
0x88100102, // 0002 GETMBR R4 R0 K2
|
||||||
|
0x5C140200, // 0003 MOVE R5 R1
|
||||||
|
0x58180005, // 0004 LDCONST R6 K5
|
||||||
|
0x7C080800, // 0005 CALL R2 4
|
||||||
|
0x940C0504, // 0006 GETIDX R3 R2 K4
|
||||||
|
0x54120007, // 0007 LDINT R4 8
|
||||||
|
0x380C0604, // 0008 SHL R3 R3 R4
|
||||||
|
0x94100503, // 0009 GETIDX R4 R2 K3
|
||||||
|
0x000C0604, // 000A ADD R3 R3 R4
|
||||||
|
0x80040600, // 000B RET 1 R3
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Solidified function: read12
|
** Solidified function: read12
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
@ -375,16 +383,82 @@ be_local_closure(class_I2C_Driver_read12, /* name */
|
|||||||
&be_const_str_read12,
|
&be_const_str_read12,
|
||||||
&be_const_str_solidified,
|
&be_const_str_solidified,
|
||||||
( &(const binstruction[12]) { /* code */
|
( &(const binstruction[12]) { /* code */
|
||||||
0x88080104, // 0000 GETMBR R2 R0 K4
|
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||||
0x8C080505, // 0001 GETMET R2 R2 K5
|
0x8C080501, // 0001 GETMET R2 R2 K1
|
||||||
0x88100106, // 0002 GETMBR R4 R0 K6
|
0x88100102, // 0002 GETMBR R4 R0 K2
|
||||||
0x5C140200, // 0003 MOVE R5 R1
|
0x5C140200, // 0003 MOVE R5 R1
|
||||||
0x58180007, // 0004 LDCONST R6 K7
|
0x58180005, // 0004 LDCONST R6 K5
|
||||||
0x7C080800, // 0005 CALL R2 4
|
0x7C080800, // 0005 CALL R2 4
|
||||||
0x940C0500, // 0006 GETIDX R3 R2 K0
|
0x940C0503, // 0006 GETIDX R3 R2 K3
|
||||||
0x54120003, // 0007 LDINT R4 4
|
0x54120003, // 0007 LDINT R4 4
|
||||||
0x380C0604, // 0008 SHL R3 R3 R4
|
0x380C0604, // 0008 SHL R3 R3 R4
|
||||||
0x94100501, // 0009 GETIDX R4 R2 K1
|
0x94100504, // 0009 GETIDX R4 R2 K4
|
||||||
|
0x000C0604, // 000A ADD R3 R3 R4
|
||||||
|
0x80040600, // 000B RET 1 R3
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: write8
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(class_I2C_Driver_write8, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
9, /* nstack */
|
||||||
|
3, /* argc */
|
||||||
|
10, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
&be_ktab_class_I2C_Driver, /* shared constants */
|
||||||
|
&be_const_str_write8,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[ 8]) { /* code */
|
||||||
|
0x880C0100, // 0000 GETMBR R3 R0 K0
|
||||||
|
0x8C0C0713, // 0001 GETMET R3 R3 K19
|
||||||
|
0x88140102, // 0002 GETMBR R5 R0 K2
|
||||||
|
0x5C180200, // 0003 MOVE R6 R1
|
||||||
|
0x5C1C0400, // 0004 MOVE R7 R2
|
||||||
|
0x58200004, // 0005 LDCONST R8 K4
|
||||||
|
0x7C0C0A00, // 0006 CALL R3 5
|
||||||
|
0x80040600, // 0007 RET 1 R3
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: read13
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(class_I2C_Driver_read13, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
7, /* nstack */
|
||||||
|
2, /* argc */
|
||||||
|
10, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
&be_ktab_class_I2C_Driver, /* shared constants */
|
||||||
|
&be_const_str_read13,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[12]) { /* code */
|
||||||
|
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||||
|
0x8C080501, // 0001 GETMET R2 R2 K1
|
||||||
|
0x88100102, // 0002 GETMBR R4 R0 K2
|
||||||
|
0x5C140200, // 0003 MOVE R5 R1
|
||||||
|
0x58180005, // 0004 LDCONST R6 K5
|
||||||
|
0x7C080800, // 0005 CALL R2 4
|
||||||
|
0x940C0503, // 0006 GETIDX R3 R2 K3
|
||||||
|
0x54120004, // 0007 LDINT R4 5
|
||||||
|
0x380C0604, // 0008 SHL R3 R3 R4
|
||||||
|
0x94100504, // 0009 GETIDX R4 R2 K4
|
||||||
0x000C0604, // 000A ADD R3 R3 R4
|
0x000C0604, // 000A ADD R3 R3 R4
|
||||||
0x80040600, // 000B RET 1 R3
|
0x80040600, // 000B RET 1 R3
|
||||||
})
|
})
|
||||||
@ -410,16 +484,16 @@ be_local_closure(class_I2C_Driver_read16, /* name */
|
|||||||
&be_const_str_read16,
|
&be_const_str_read16,
|
||||||
&be_const_str_solidified,
|
&be_const_str_solidified,
|
||||||
( &(const binstruction[12]) { /* code */
|
( &(const binstruction[12]) { /* code */
|
||||||
0x88080104, // 0000 GETMBR R2 R0 K4
|
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||||
0x8C080505, // 0001 GETMET R2 R2 K5
|
0x8C080501, // 0001 GETMET R2 R2 K1
|
||||||
0x88100106, // 0002 GETMBR R4 R0 K6
|
0x88100102, // 0002 GETMBR R4 R0 K2
|
||||||
0x5C140200, // 0003 MOVE R5 R1
|
0x5C140200, // 0003 MOVE R5 R1
|
||||||
0x58180007, // 0004 LDCONST R6 K7
|
0x58180005, // 0004 LDCONST R6 K5
|
||||||
0x7C080800, // 0005 CALL R2 4
|
0x7C080800, // 0005 CALL R2 4
|
||||||
0x940C0500, // 0006 GETIDX R3 R2 K0
|
0x940C0503, // 0006 GETIDX R3 R2 K3
|
||||||
0x54120007, // 0007 LDINT R4 8
|
0x54120007, // 0007 LDINT R4 8
|
||||||
0x380C0604, // 0008 SHL R3 R3 R4
|
0x380C0604, // 0008 SHL R3 R3 R4
|
||||||
0x94100501, // 0009 GETIDX R4 R2 K1
|
0x94100504, // 0009 GETIDX R4 R2 K4
|
||||||
0x000C0604, // 000A ADD R3 R3 R4
|
0x000C0604, // 000A ADD R3 R3 R4
|
||||||
0x80040600, // 000B RET 1 R3
|
0x80040600, // 000B RET 1 R3
|
||||||
})
|
})
|
||||||
@ -428,27 +502,61 @@ be_local_closure(class_I2C_Driver_read16, /* name */
|
|||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: write16
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(class_I2C_Driver_write16, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
9, /* nstack */
|
||||||
|
3, /* argc */
|
||||||
|
10, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
&be_ktab_class_I2C_Driver, /* shared constants */
|
||||||
|
&be_const_str_write16,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[ 8]) { /* code */
|
||||||
|
0x880C0100, // 0000 GETMBR R3 R0 K0
|
||||||
|
0x8C0C0713, // 0001 GETMET R3 R3 K19
|
||||||
|
0x88140102, // 0002 GETMBR R5 R0 K2
|
||||||
|
0x5C180200, // 0003 MOVE R6 R1
|
||||||
|
0x5C1C0400, // 0004 MOVE R7 R2
|
||||||
|
0x58200005, // 0005 LDCONST R8 K5
|
||||||
|
0x7C0C0A00, // 0006 CALL R3 5
|
||||||
|
0x80040600, // 0007 RET 1 R3
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Solidified class: I2C_Driver
|
** Solidified class: I2C_Driver
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
be_local_class(I2C_Driver,
|
be_local_class(I2C_Driver,
|
||||||
3,
|
3,
|
||||||
NULL,
|
NULL,
|
||||||
be_nested_map(13,
|
be_nested_map(16,
|
||||||
( (struct bmapnode*) &(const bmapnode[]) {
|
( (struct bmapnode*) &(const bmapnode[]) {
|
||||||
{ be_const_key(write_bit, -1), be_const_closure(class_I2C_Driver_write_bit_closure) },
|
|
||||||
{ be_const_key(addr, -1), be_const_var(1) },
|
|
||||||
{ be_const_key(read32, -1), be_const_closure(class_I2C_Driver_read32_closure) },
|
{ be_const_key(read32, -1), be_const_closure(class_I2C_Driver_read32_closure) },
|
||||||
|
{ be_const_key(write16, 15), be_const_closure(class_I2C_Driver_write16_closure) },
|
||||||
|
{ be_const_key(addr, -1), be_const_var(1) },
|
||||||
|
{ be_const_key(init, 1), be_const_closure(class_I2C_Driver_init_closure) },
|
||||||
|
{ be_const_key(write_bit, -1), be_const_closure(class_I2C_Driver_write_bit_closure) },
|
||||||
|
{ be_const_key(read14, -1), be_const_closure(class_I2C_Driver_read14_closure) },
|
||||||
|
{ be_const_key(name, -1), be_const_var(2) },
|
||||||
|
{ be_const_key(read8, -1), be_const_closure(class_I2C_Driver_read8_closure) },
|
||||||
|
{ be_const_key(write16LE, 11), be_const_closure(class_I2C_Driver_write16LE_closure) },
|
||||||
|
{ be_const_key(read16LE, -1), be_const_closure(class_I2C_Driver_read16LE_closure) },
|
||||||
|
{ be_const_key(read12, -1), be_const_closure(class_I2C_Driver_read12_closure) },
|
||||||
|
{ be_const_key(wire, 5), be_const_var(0) },
|
||||||
|
{ be_const_key(write8, -1), be_const_closure(class_I2C_Driver_write8_closure) },
|
||||||
{ be_const_key(read13, -1), be_const_closure(class_I2C_Driver_read13_closure) },
|
{ be_const_key(read13, -1), be_const_closure(class_I2C_Driver_read13_closure) },
|
||||||
{ be_const_key(read16, -1), be_const_closure(class_I2C_Driver_read16_closure) },
|
{ be_const_key(read16, -1), be_const_closure(class_I2C_Driver_read16_closure) },
|
||||||
{ be_const_key(read14, -1), be_const_closure(class_I2C_Driver_read14_closure) },
|
{ be_const_key(read24, -1), be_const_closure(class_I2C_Driver_read24_closure) },
|
||||||
{ be_const_key(read24, 12), be_const_closure(class_I2C_Driver_read24_closure) },
|
|
||||||
{ be_const_key(name, 4), be_const_var(2) },
|
|
||||||
{ be_const_key(write8, -1), be_const_closure(class_I2C_Driver_write8_closure) },
|
|
||||||
{ be_const_key(wire, 8), be_const_var(0) },
|
|
||||||
{ be_const_key(read8, -1), be_const_closure(class_I2C_Driver_read8_closure) },
|
|
||||||
{ be_const_key(read12, -1), be_const_closure(class_I2C_Driver_read12_closure) },
|
|
||||||
{ be_const_key(init, -1), be_const_closure(class_I2C_Driver_init_closure) },
|
|
||||||
})),
|
})),
|
||||||
(bstring*) &be_const_str_I2C_Driver
|
(bstring*) &be_const_str_I2C_Driver
|
||||||
);
|
);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -31,6 +31,7 @@ idf_component_register(
|
|||||||
"esp32c2"
|
"esp32c2"
|
||||||
"esp32c3"
|
"esp32c3"
|
||||||
"esp32c6"
|
"esp32c6"
|
||||||
|
"esp32h2"
|
||||||
INCLUDE_DIRS
|
INCLUDE_DIRS
|
||||||
"src"
|
"src"
|
||||||
SRCS
|
SRCS
|
||||||
@ -58,6 +59,7 @@ idf_component_register(
|
|||||||
REQUIRES
|
REQUIRES
|
||||||
bt
|
bt
|
||||||
nvs_flash
|
nvs_flash
|
||||||
|
driver
|
||||||
PRIV_REQUIRES
|
PRIV_REQUIRES
|
||||||
${ESP_NIMBLE_PRIV_REQUIRES}
|
${ESP_NIMBLE_PRIV_REQUIRES}
|
||||||
)
|
)
|
||||||
|
|||||||
@ -33,7 +33,7 @@ config NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
|||||||
Enabling this option will display return code values as text
|
Enabling this option will display return code values as text
|
||||||
messages in the debug log. This will use approximately 8kB
|
messages in the debug log. This will use approximately 8kB
|
||||||
of flash memory.
|
of flash memory.
|
||||||
|
|
||||||
config NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
config NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||||
bool "Show NimBLE gap events as text in debug log."
|
bool "Show NimBLE gap events as text in debug log."
|
||||||
default "n"
|
default "n"
|
||||||
@ -47,7 +47,7 @@ config NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT
|
|||||||
default "n"
|
default "n"
|
||||||
help
|
help
|
||||||
Enabling this option will display advertisment types recieved
|
Enabling this option will display advertisment types recieved
|
||||||
while scanning as text messages in the debug log.
|
while scanning as text messages in the debug log.
|
||||||
This will use approximately 250 bytes of flash memory.
|
This will use approximately 250 bytes of flash memory.
|
||||||
|
|
||||||
config NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
config NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||||
@ -68,5 +68,12 @@ config NIMBLE_CPP_ATT_VALUE_INIT_LENGTH
|
|||||||
when the constructor is called. This is also the size used when a remote
|
when the constructor is called. This is also the size used when a remote
|
||||||
characteristic or descriptor is constructed before a value is read/notifed.
|
characteristic or descriptor is constructed before a value is read/notifed.
|
||||||
Increasing this will reduce reallocations but increase memory footprint.
|
Increasing this will reduce reallocations but increase memory footprint.
|
||||||
|
|
||||||
|
config NIMBLE_CPP_DEBUG_ASSERT_ENABLED
|
||||||
|
bool "Enable debug asserts."
|
||||||
|
default "n"
|
||||||
|
help
|
||||||
|
Enabling this option will add debug asserts to the NimBLE CPP library.
|
||||||
|
This will use approximately 1kB of flash memory.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|||||||
@ -66,7 +66,7 @@ If false the service is only removed from visibility by clients. The pointers to
|
|||||||
# Advertising
|
# Advertising
|
||||||
`NimBLEAdvertising::start`
|
`NimBLEAdvertising::start`
|
||||||
|
|
||||||
Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
Now takes 2 optional parameters, the first is the duration to advertise for (in milliseconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
||||||
|
|
||||||
This provides an opportunity to update the advertisement data if desired.
|
This provides an opportunity to update the advertisement data if desired.
|
||||||
|
|
||||||
|
|||||||
@ -255,7 +255,7 @@ Calling `NimBLEAdvertising::setAdvertisementData` will entirely replace any data
|
|||||||
|
|
||||||
> BLEAdvertising::start (NimBLEAdvertising::start)
|
> BLEAdvertising::start (NimBLEAdvertising::start)
|
||||||
|
|
||||||
Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
Now takes 2 optional parameters, the first is the duration to advertise for (in milliseconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
||||||
This provides an opportunity to update the advertisement data if desired.
|
This provides an opportunity to update the advertisement data if desired.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
@ -383,18 +383,23 @@ The security callback methods are now incorporated in the `NimBLEServerCallbacks
|
|||||||
|
|
||||||
The callback methods are:
|
The callback methods are:
|
||||||
|
|
||||||
> `bool onConfirmPIN(uint32_t pin)`
|
> `bool onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pin)`
|
||||||
|
|
||||||
Receives the pin when using numeric comparison authentication, `return true;` to accept.
|
Receives the pin when using numeric comparison authentication.
|
||||||
|
Call `NimBLEDevice::injectConfirmPIN(connInfo, true);` to accept or `NimBLEDevice::injectConfirmPIN(connInfo, false);` to reject.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
> `uint32_t onPassKeyRequest()`
|
> `void onPassKeyEntry(const NimBLEConnInfo& connInfo)`
|
||||||
|
|
||||||
For server callback; return the passkey expected from the client.
|
Client callback; client should respond with the passkey (pin) by calling `NimBLEDevice::injectPassKey(connInfo, 123456);`
|
||||||
For client callback; return the passkey to send to the server.
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
> `void onAuthenticationComplete(NimBLEConnInfo& connInfo)`
|
> `uint32_t onPassKeyDisplay()`
|
||||||
|
|
||||||
|
Server callback; should return the passkey (pin) expected from the client.
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
> `void onAuthenticationComplete(const NimBLEConnInfo& connInfo)`
|
||||||
|
|
||||||
Authentication complete, success or failed information is available from the `NimBLEConnInfo` methods.
|
Authentication complete, success or failed information is available from the `NimBLEConnInfo` methods.
|
||||||
<br/>
|
<br/>
|
||||||
|
|||||||
@ -39,20 +39,22 @@ class ClientCallbacks : public NimBLEClientCallbacks {
|
|||||||
|
|
||||||
/********************* Security handled here **********************
|
/********************* Security handled here **********************
|
||||||
****** Note: these are the same return values as defaults ********/
|
****** Note: these are the same return values as defaults ********/
|
||||||
uint32_t onPassKeyRequest(){
|
void onPassKeyEntry(const NimBLEConnInfo& connInfo){
|
||||||
printf("Client Passkey Request\n");
|
printf("Server Passkey Entry\n");
|
||||||
/** return the passkey to send to the server */
|
/** This should prompt the user to enter the passkey displayed
|
||||||
return 123456;
|
* on the peer device.
|
||||||
}
|
*/
|
||||||
|
NimBLEDevice::injectPassKey(connInfo, 123456);
|
||||||
|
};
|
||||||
|
|
||||||
bool onConfirmPIN(uint32_t pass_key){
|
void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pass_key){
|
||||||
printf("The passkey YES/NO number: %" PRIu32"\n", pass_key);
|
printf("The passkey YES/NO number: %" PRIu32 "\n", pass_key);
|
||||||
/** Return false if passkeys don't match. */
|
/** Inject false if passkeys don't match. */
|
||||||
return true;
|
NimBLEDevice::injectConfirmPIN(connInfo, true);
|
||||||
}
|
};
|
||||||
|
|
||||||
/** Pairing process complete, we can check the results in connInfo */
|
/** Pairing process complete, we can check the results in connInfo */
|
||||||
void onAuthenticationComplete(NimBLEConnInfo& connInfo){
|
void onAuthenticationComplete(const NimBLEConnInfo& connInfo){
|
||||||
if(!connInfo.isEncrypted()) {
|
if(!connInfo.isEncrypted()) {
|
||||||
printf("Encrypt connection failed - disconnecting\n");
|
printf("Encrypt connection failed - disconnecting\n");
|
||||||
/** Find the client with the connection handle provided in desc */
|
/** Find the client with the connection handle provided in desc */
|
||||||
@ -146,8 +148,8 @@ bool connectToServer() {
|
|||||||
* Min interval: 12 * 1.25ms = 15, Max interval: 12 * 1.25ms = 15, 0 latency, 12 * 10ms = 120ms timeout
|
* Min interval: 12 * 1.25ms = 15, Max interval: 12 * 1.25ms = 15, 0 latency, 12 * 10ms = 120ms timeout
|
||||||
*/
|
*/
|
||||||
pClient->setConnectionParams(6,6,0,15);
|
pClient->setConnectionParams(6,6,0,15);
|
||||||
/** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */
|
/** Set how long we are willing to wait for the connection to complete (milliseconds), default is 30000. */
|
||||||
pClient->setConnectTimeout(5);
|
pClient->setConnectTimeout(5 * 1000);
|
||||||
|
|
||||||
|
|
||||||
if (!pClient->connect(advDevice)) {
|
if (!pClient->connect(advDevice)) {
|
||||||
@ -358,7 +360,7 @@ void app_main (void){
|
|||||||
* but will use more energy from both devices
|
* but will use more energy from both devices
|
||||||
*/
|
*/
|
||||||
pScan->setActiveScan(true);
|
pScan->setActiveScan(true);
|
||||||
/** Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
|
/** Start scanning for advertisers for the scan time specified (in milliseconds) 0 = forever
|
||||||
* Optional callback for when scanning stops.
|
* Optional callback for when scanning stops.
|
||||||
*/
|
*/
|
||||||
pScan->start(scanTime);
|
pScan->start(scanTime);
|
||||||
|
|||||||
@ -44,21 +44,21 @@ class ServerCallbacks: public NimBLEServerCallbacks {
|
|||||||
|
|
||||||
/********************* Security handled here **********************
|
/********************* Security handled here **********************
|
||||||
****** Note: these are the same return values as defaults ********/
|
****** Note: these are the same return values as defaults ********/
|
||||||
uint32_t onPassKeyRequest(){
|
uint32_t onPassKeyDisplay(){
|
||||||
printf("Server Passkey Request\n");
|
printf("Server Passkey Display\n");
|
||||||
/** This should return a random 6 digit number for security
|
/** This should return a random 6 digit number for security
|
||||||
* or make your own static passkey as done here.
|
* or make your own static passkey as done here.
|
||||||
*/
|
*/
|
||||||
return 123456;
|
return 123456;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool onConfirmPIN(uint32_t pass_key){
|
void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pass_key){
|
||||||
printf("The passkey YES/NO number: %" PRIu32"\n", pass_key);
|
printf("The passkey YES/NO number: %" PRIu32 "\n", pass_key);
|
||||||
/** Return false if passkeys don't match. */
|
/** Inject false if passkeys don't match. */
|
||||||
return true;
|
NimBLEDevice::injectConfirmPIN(connInfo, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
void onAuthenticationComplete(NimBLEConnInfo& connInfo){
|
void onAuthenticationComplete(const NimBLEConnInfo& connInfo){
|
||||||
/** Check that encryption was successful, if not we disconnect the client */
|
/** Check that encryption was successful, if not we disconnect the client */
|
||||||
if(!connInfo.isEncrypted()) {
|
if(!connInfo.isEncrypted()) {
|
||||||
NimBLEDevice::getServer()->disconnect(connInfo.getConnHandle());
|
NimBLEDevice::getServer()->disconnect(connInfo.getConnHandle());
|
||||||
|
|||||||
@ -154,7 +154,7 @@ void app_main (void) {
|
|||||||
*/
|
*/
|
||||||
pScan->setActiveScan(true);
|
pScan->setActiveScan(true);
|
||||||
|
|
||||||
/* Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
|
/* Start scanning for advertisers for the scan time specified (in milliseconds) 0 = forever
|
||||||
* Optional callback for when scanning stops.
|
* Optional callback for when scanning stops.
|
||||||
*/
|
*/
|
||||||
pScan->start(scanTime);
|
pScan->start(scanTime);
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* NimBLE Scan active/passive switching demo
|
|
||||||
*
|
|
||||||
* Demonstrates the use of the scan callbacks while alternating between passive and active scanning.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "NimBLEDevice.h"
|
|
||||||
int scanTime = 5 * 1000; // In milliseconds, 0 = scan forever
|
|
||||||
BLEScan* pBLEScan;
|
|
||||||
|
|
||||||
bool active = false;
|
|
||||||
|
|
||||||
class scanCallbacks: public NimBLEScanCallbacks {
|
|
||||||
|
|
||||||
void onDiscovered(NimBLEAdvertisedDevice* advertisedDevice) {
|
|
||||||
Serial.printf("Discovered Advertised Device: %s \n", advertisedDevice->toString().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
|
|
||||||
Serial.printf("Advertised Device Result: %s \n", advertisedDevice->toString().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void onScanEnd(NimBLEScanResults results){
|
|
||||||
Serial.println("Scan Ended");
|
|
||||||
active = !active;
|
|
||||||
pBLEScan->setActiveScan(active);
|
|
||||||
Serial.printf("scan start, active = %u\n", active);
|
|
||||||
pBLEScan->start(scanTime);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
Serial.begin(115200);
|
|
||||||
Serial.println("Scanning...");
|
|
||||||
|
|
||||||
NimBLEDevice::init("");
|
|
||||||
pBLEScan = NimBLEDevice::getScan();
|
|
||||||
pBLEScan->setScanCallbacks(new scanCallbacks());
|
|
||||||
pBLEScan->setActiveScan(active);
|
|
||||||
pBLEScan->setInterval(100);
|
|
||||||
pBLEScan->setWindow(99);
|
|
||||||
pBLEScan->start(scanTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
}
|
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
# The following lines of boilerplate have to be in your project's
|
||||||
|
# CMakeLists in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
set(SUPPORTED_TARGETS esp32)
|
||||||
|
project(NimBLE_server_get_client_name)
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
set(COMPONENT_SRCS "main.cpp")
|
||||||
|
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||||
|
|
||||||
|
register_component()
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
/** NimBLE_server_get_client_name
|
||||||
|
*
|
||||||
|
* Demonstrates 2 ways for the server to read the device name from the connected client.
|
||||||
|
*
|
||||||
|
* Created: on June 24 2024
|
||||||
|
* Author: H2zero
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <NimBLEDevice.h>
|
||||||
|
|
||||||
|
// See the following for generating UUIDs:
|
||||||
|
// https://www.uuidgenerator.net/
|
||||||
|
|
||||||
|
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
|
||||||
|
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
|
||||||
|
#define ENC_CHARACTERISTIC_UUID "9551f35b-8d91-42e4-8f7e-1358dfe272dc"
|
||||||
|
|
||||||
|
NimBLEServer* pServer;
|
||||||
|
|
||||||
|
class ServerCallbacks : public NimBLEServerCallbacks {
|
||||||
|
// Same as before but now includes the name parameter
|
||||||
|
void onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, std::string& name) override {
|
||||||
|
printf("Client address: %s Name: %s\n", connInfo.getAddress().toString().c_str(), name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as before but now includes the name parameter
|
||||||
|
void onAuthenticationComplete(const NimBLEConnInfo& connInfo, const std::string& name) override {
|
||||||
|
if (!connInfo.isEncrypted()) {
|
||||||
|
NimBLEDevice::getServer()->disconnect(connInfo.getConnHandle());
|
||||||
|
printf("Encrypt connection failed - disconnecting client\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Encrypted Client address: %s Name: %s\n", connInfo.getAddress().toString().c_str(), name.c_str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" void app_main(void) {
|
||||||
|
printf("Starting BLE Server!\n");
|
||||||
|
|
||||||
|
NimBLEDevice::init("Connect to me!");
|
||||||
|
NimBLEDevice::setSecurityAuth(true, false, true); // Enable bonding to see full name on phones.
|
||||||
|
|
||||||
|
pServer = NimBLEDevice::createServer();
|
||||||
|
NimBLEService* pService = pServer->createService(SERVICE_UUID);
|
||||||
|
NimBLECharacteristic* pCharacteristic =
|
||||||
|
pService->createCharacteristic(CHARACTERISTIC_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE);
|
||||||
|
pCharacteristic->setValue("Hello World says NimBLE!");
|
||||||
|
|
||||||
|
NimBLECharacteristic* pEncCharacteristic = pService->createCharacteristic(
|
||||||
|
ENC_CHARACTERISTIC_UUID,
|
||||||
|
(NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC));
|
||||||
|
pEncCharacteristic->setValue("Hello World says NimBLE Encrypted");
|
||||||
|
|
||||||
|
pService->start();
|
||||||
|
|
||||||
|
pServer->setCallbacks(new ServerCallbacks());
|
||||||
|
pServer->getPeerNameOnConnect(true); // Setting this will enable the onConnect callback that provides the name.
|
||||||
|
|
||||||
|
BLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
|
||||||
|
pAdvertising->addServiceUUID(SERVICE_UUID);
|
||||||
|
pAdvertising->setScanResponse(true);
|
||||||
|
|
||||||
|
pAdvertising->start();
|
||||||
|
printf("Advertising started, connect with your phone.\n");
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
auto clientCount = pServer->getConnectedCount();
|
||||||
|
if (clientCount) {
|
||||||
|
printf("Connected clients:\n");
|
||||||
|
for (auto i = 0; i < clientCount; ++i) {
|
||||||
|
NimBLEConnInfo peerInfo = pServer->getPeerInfo(i);
|
||||||
|
printf("Client address: %s Name: %s\n", peerInfo.getAddress().toString().c_str(),
|
||||||
|
// This function blocks until the name is retrieved, so cannot be used in callback functions.
|
||||||
|
pServer->getPeerName(peerInfo).c_str());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -51,17 +51,28 @@ class MyClientCallback : public BLEClientCallbacks {
|
|||||||
}
|
}
|
||||||
/***************** New - Security handled here ********************
|
/***************** New - Security handled here ********************
|
||||||
****** Note: these are the same return values as defaults ********/
|
****** Note: these are the same return values as defaults ********/
|
||||||
uint32_t onPassKeyRequest(){
|
void onPassKeyEntry(const NimBLEConnInfo& connInfo){
|
||||||
printf("Client PassKeyRequest\n");
|
printf("Server Passkey Entry\n");
|
||||||
return 123456;
|
/** This should prompt the user to enter the passkey displayed
|
||||||
}
|
* on the peer device.
|
||||||
bool onConfirmPIN(uint32_t pass_key){
|
*/
|
||||||
printf("The passkey YES/NO number: %" PRIu32"\n", pass_key);
|
NimBLEDevice::injectPassKey(connInfo, 123456);
|
||||||
return true;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
void onAuthenticationComplete(BLEConnInfo& connInfo){
|
void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pass_key){
|
||||||
printf("Starting BLE work!\n");
|
printf("The passkey YES/NO number: %" PRIu32 "\n", pass_key);
|
||||||
|
/** Inject false if passkeys don't match. */
|
||||||
|
NimBLEDevice::injectConfirmPIN(connInfo, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Pairing process complete, we can check the results in connInfo */
|
||||||
|
void onAuthenticationComplete(const NimBLEConnInfo& connInfo){
|
||||||
|
if(!connInfo.isEncrypted()) {
|
||||||
|
printf("Encrypt connection failed - disconnecting\n");
|
||||||
|
/** Find the client with the connection handle provided in desc */
|
||||||
|
NimBLEDevice::getClientByID(connInfo.getConnHandle())->disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
};
|
};
|
||||||
|
|||||||
@ -57,19 +57,29 @@ class MyServerCallbacks: public BLEServerCallbacks {
|
|||||||
}
|
}
|
||||||
/***************** New - Security handled here ********************
|
/***************** New - Security handled here ********************
|
||||||
****** Note: these are the same return values as defaults ********/
|
****** Note: these are the same return values as defaults ********/
|
||||||
uint32_t onPassKeyRequest(){
|
uint32_t onPassKeyDisplay(){
|
||||||
printf("Server PassKeyRequest\n");
|
printf("Server Passkey Display\n");
|
||||||
return 123456;
|
/** This should return a random 6 digit number for security
|
||||||
}
|
* or make your own static passkey as done here.
|
||||||
|
*/
|
||||||
|
return 123456;
|
||||||
|
};
|
||||||
|
|
||||||
bool onConfirmPIN(uint32_t pass_key){
|
void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pass_key){
|
||||||
printf("The passkey YES/NO number: %" PRIu32"\n", pass_key);
|
printf("The passkey YES/NO number: %" PRIu32 "\n", pass_key);
|
||||||
return true;
|
/** Inject false if passkeys don't match. */
|
||||||
}
|
NimBLEDevice::injectConfirmPIN(connInfo, true);
|
||||||
|
};
|
||||||
|
|
||||||
void onAuthenticationComplete(BLEConnInfo& connInfo){
|
void onAuthenticationComplete(const NimBLEConnInfo& connInfo){
|
||||||
printf("Starting BLE work!\n");
|
/** Check that encryption was successful, if not we disconnect the client */
|
||||||
}
|
if(!connInfo.isEncrypted()) {
|
||||||
|
NimBLEDevice::getServer()->disconnect(connInfo.getConnHandle());
|
||||||
|
printf("Encrypt connection failed - disconnecting client\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("Starting BLE work!");
|
||||||
|
};
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -128,7 +138,6 @@ void app_main(void) {
|
|||||||
NIMBLE_PROPERTY::INDICATE
|
NIMBLE_PROPERTY::INDICATE
|
||||||
);
|
);
|
||||||
|
|
||||||
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
|
|
||||||
// Create a BLE Descriptor
|
// Create a BLE Descriptor
|
||||||
/***************************************************
|
/***************************************************
|
||||||
NOTE: DO NOT create a 2902 descriptor.
|
NOTE: DO NOT create a 2902 descriptor.
|
||||||
|
|||||||
@ -59,19 +59,29 @@ class MyServerCallbacks: public BLEServerCallbacks {
|
|||||||
}
|
}
|
||||||
/***************** New - Security handled here ********************
|
/***************** New - Security handled here ********************
|
||||||
****** Note: these are the same return values as defaults ********/
|
****** Note: these are the same return values as defaults ********/
|
||||||
uint32_t onPassKeyRequest(){
|
uint32_t onPassKeyDisplay(){
|
||||||
printf("Server PassKeyRequest\n");
|
printf("Server Passkey Display\n");
|
||||||
return 123456;
|
/** This should return a random 6 digit number for security
|
||||||
}
|
* or make your own static passkey as done here.
|
||||||
|
*/
|
||||||
|
return 123456;
|
||||||
|
};
|
||||||
|
|
||||||
bool onConfirmPIN(uint32_t pass_key){
|
void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pass_key){
|
||||||
printf("The passkey YES/NO number: %" PRIu32"\n", pass_key);
|
printf("The passkey YES/NO number: %" PRIu32 "\n", pass_key);
|
||||||
return true;
|
/** Inject false if passkeys don't match. */
|
||||||
}
|
NimBLEDevice::injectConfirmPIN(connInfo, true);
|
||||||
|
};
|
||||||
|
|
||||||
void onAuthenticationComplete(BLEConnInfo& connInfo){
|
void onAuthenticationComplete(const NimBLEConnInfo& connInfo){
|
||||||
printf("Starting BLE work!\n");
|
/** Check that encryption was successful, if not we disconnect the client */
|
||||||
}
|
if(!connInfo.isEncrypted()) {
|
||||||
|
NimBLEDevice::getServer()->disconnect(connInfo.getConnHandle());
|
||||||
|
printf("Encrypt connection failed - disconnecting client\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("Starting BLE work!");
|
||||||
|
};
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
17
lib/libesp32_div/esp-nimble-cpp/package.json
Normal file
17
lib/libesp32_div/esp-nimble-cpp/package.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "esp-nimble-cpp",
|
||||||
|
"version": "1.5.0",
|
||||||
|
"description": "NimBLE, BLE stack for the Espressif ESP32, ESP32-S and ESP32-C series of SoCs",
|
||||||
|
"keywords": [
|
||||||
|
"BLE",
|
||||||
|
"espidf",
|
||||||
|
"arduino",
|
||||||
|
"espressif",
|
||||||
|
"esp32"
|
||||||
|
],
|
||||||
|
"license": "LGPL-2.1-or-later",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/h2zero/esp-nimble-cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,10 +12,6 @@
|
|||||||
* Author: kolban
|
* Author: kolban
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* See also:
|
|
||||||
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
|
|
||||||
*/
|
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
|
|||||||
@ -33,9 +33,6 @@ struct BLE2904_Data {
|
|||||||
* @brief Descriptor for Characteristic Presentation Format.
|
* @brief Descriptor for Characteristic Presentation Format.
|
||||||
*
|
*
|
||||||
* This is a convenience descriptor for the Characteristic Presentation Format which has a UUID of 0x2904.
|
* This is a convenience descriptor for the Characteristic Presentation Format which has a UUID of 0x2904.
|
||||||
*
|
|
||||||
* See also:
|
|
||||||
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
|
|
||||||
*/
|
*/
|
||||||
class NimBLE2904: public NimBLEDescriptor {
|
class NimBLE2904: public NimBLEDescriptor {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -138,6 +138,15 @@ uint8_t NimBLEAddress::getType() const {
|
|||||||
} // getType
|
} // getType
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Determine if this address is a Resolvable Private Address.
|
||||||
|
* @return True if the address is a RPA.
|
||||||
|
*/
|
||||||
|
bool NimBLEAddress::isRpa() const {
|
||||||
|
return (m_addrType && ((m_address[5] & 0xc0) == 0x40));
|
||||||
|
} // isRpa
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert a BLE address to a string.
|
* @brief Convert a BLE address to a string.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -43,6 +43,7 @@ public:
|
|||||||
NimBLEAddress(uint8_t address[6], uint8_t type = BLE_ADDR_PUBLIC);
|
NimBLEAddress(uint8_t address[6], uint8_t type = BLE_ADDR_PUBLIC);
|
||||||
NimBLEAddress(const std::string &stringAddress, uint8_t type = BLE_ADDR_PUBLIC);
|
NimBLEAddress(const std::string &stringAddress, uint8_t type = BLE_ADDR_PUBLIC);
|
||||||
NimBLEAddress(const uint64_t &address, uint8_t type = BLE_ADDR_PUBLIC);
|
NimBLEAddress(const uint64_t &address, uint8_t type = BLE_ADDR_PUBLIC);
|
||||||
|
bool isRpa() const;
|
||||||
bool equals(const NimBLEAddress &otherAddress) const;
|
bool equals(const NimBLEAddress &otherAddress) const;
|
||||||
const uint8_t* getNative() const;
|
const uint8_t* getNative() const;
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|||||||
@ -203,6 +203,24 @@ std::string NimBLEAdvertisedDevice::getURI() {
|
|||||||
return "";
|
return "";
|
||||||
} // getURI
|
} // getURI
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the data from any type available in the advertisement
|
||||||
|
* @param [in] type The advertised data type BLE_HS_ADV_TYPE
|
||||||
|
* @return The data available under the type `type`
|
||||||
|
*/
|
||||||
|
std::string NimBLEAdvertisedDevice::getPayloadByType(uint16_t type) {
|
||||||
|
size_t data_loc = 0;
|
||||||
|
|
||||||
|
if(findAdvField(type, 0, &data_loc) > 0) {
|
||||||
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
|
if(field->length > 1) {
|
||||||
|
return std::string((char*)field->value, field->length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
} // getPayloadByType
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the advertised name.
|
* @brief Get the advertised name.
|
||||||
@ -556,6 +574,14 @@ bool NimBLEAdvertisedDevice::haveURI() {
|
|||||||
return findAdvField(BLE_HS_ADV_TYPE_URI) > 0;
|
return findAdvField(BLE_HS_ADV_TYPE_URI) > 0;
|
||||||
} // haveURI
|
} // haveURI
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Does this advertisement have a adv type `type`?
|
||||||
|
* @return True if there is a `type` present.
|
||||||
|
*/
|
||||||
|
bool NimBLEAdvertisedDevice::haveType(uint16_t type) {
|
||||||
|
return findAdvField(type) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Does the advertisement contain a target address?
|
* @brief Does the advertisement contain a target address?
|
||||||
|
|||||||
@ -53,6 +53,7 @@ public:
|
|||||||
uint8_t getManufacturerDataCount();
|
uint8_t getManufacturerDataCount();
|
||||||
std::string getManufacturerData(uint8_t index = 0);
|
std::string getManufacturerData(uint8_t index = 0);
|
||||||
std::string getURI();
|
std::string getURI();
|
||||||
|
std::string getPayloadByType(uint16_t type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A template to convert the service data to <type\>.
|
* @brief A template to convert the service data to <type\>.
|
||||||
@ -134,6 +135,7 @@ public:
|
|||||||
bool haveAdvInterval();
|
bool haveAdvInterval();
|
||||||
bool haveTargetAddress();
|
bool haveTargetAddress();
|
||||||
bool haveURI();
|
bool haveURI();
|
||||||
|
bool haveType(uint16_t type);
|
||||||
std::string toString();
|
std::string toString();
|
||||||
bool isConnectable();
|
bool isConnectable();
|
||||||
bool isLegacyAdvertisement();
|
bool isLegacyAdvertisement();
|
||||||
|
|||||||
@ -96,8 +96,8 @@ void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add a service uuid to exposed list of services.
|
* @brief Remove a service UUID from the advertisment.
|
||||||
* @param [in] serviceUUID The UUID of the service to expose.
|
* @param [in] serviceUUID The UUID of the service to remove.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertising::removeServiceUUID(const NimBLEUUID &serviceUUID) {
|
void NimBLEAdvertising::removeServiceUUID(const NimBLEUUID &serviceUUID) {
|
||||||
for(auto it = m_serviceUUIDs.begin(); it != m_serviceUUIDs.end(); ++it) {
|
for(auto it = m_serviceUUIDs.begin(); it != m_serviceUUIDs.end(); ++it) {
|
||||||
@ -110,10 +110,17 @@ void NimBLEAdvertising::removeServiceUUID(const NimBLEUUID &serviceUUID) {
|
|||||||
} // addServiceUUID
|
} // addServiceUUID
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove all service UUIDs from the advertisment.
|
||||||
|
*/
|
||||||
|
void NimBLEAdvertising::removeServices() {
|
||||||
|
std::vector<NimBLEUUID>().swap(m_serviceUUIDs);
|
||||||
|
m_advDataSet = false;
|
||||||
|
} // removeServices
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the device appearance in the advertising data.
|
* @brief Set the device appearance in the advertising data.
|
||||||
* The codes for distinct appearances can be found here:\n
|
|
||||||
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml.
|
|
||||||
* @param [in] appearance The appearance of the device in the advertising data.
|
* @param [in] appearance The appearance of the device in the advertising data.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertising::setAppearance(uint16_t appearance) {
|
void NimBLEAdvertising::setAppearance(uint16_t appearance) {
|
||||||
@ -137,7 +144,7 @@ void NimBLEAdvertising::addTxPower() {
|
|||||||
* @param [in] name The name to advertise.
|
* @param [in] name The name to advertise.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertising::setName(const std::string &name) {
|
void NimBLEAdvertising::setName(const std::string &name) {
|
||||||
m_name.assign(name.begin(), name.end());
|
std::vector<uint8_t>(name.begin(), name.end()).swap(m_name);
|
||||||
m_advData.name = &m_name[0];
|
m_advData.name = &m_name[0];
|
||||||
m_advData.name_len = m_name.size();
|
m_advData.name_len = m_name.size();
|
||||||
m_advDataSet = false;
|
m_advDataSet = false;
|
||||||
@ -149,7 +156,7 @@ void NimBLEAdvertising::setName(const std::string &name) {
|
|||||||
* @param [in] data The data to advertise.
|
* @param [in] data The data to advertise.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertising::setManufacturerData(const std::string &data) {
|
void NimBLEAdvertising::setManufacturerData(const std::string &data) {
|
||||||
m_mfgData.assign(data.begin(), data.end());
|
std::vector<uint8_t>(data.begin(), data.end()).swap(m_mfgData);
|
||||||
m_advData.mfg_data = &m_mfgData[0];
|
m_advData.mfg_data = &m_mfgData[0];
|
||||||
m_advData.mfg_data_len = m_mfgData.size();
|
m_advData.mfg_data_len = m_mfgData.size();
|
||||||
m_advDataSet = false;
|
m_advDataSet = false;
|
||||||
@ -173,7 +180,7 @@ void NimBLEAdvertising::setManufacturerData(const std::vector<uint8_t> &data) {
|
|||||||
* @param [in] uri The URI to advertise.
|
* @param [in] uri The URI to advertise.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertising::setURI(const std::string &uri) {
|
void NimBLEAdvertising::setURI(const std::string &uri) {
|
||||||
m_uri.assign(uri.begin(), uri.end());
|
std::vector<uint8_t>(uri.begin(), uri.end()).swap(m_uri);
|
||||||
m_advData.uri = &m_uri[0];
|
m_advData.uri = &m_uri[0];
|
||||||
m_advData.uri_len = m_uri.size();
|
m_advData.uri_len = m_uri.size();
|
||||||
m_advDataSet = false;
|
m_advDataSet = false;
|
||||||
@ -189,7 +196,8 @@ void NimBLEAdvertising::setURI(const std::string &uri) {
|
|||||||
void NimBLEAdvertising::setServiceData(const NimBLEUUID &uuid, const std::string &data) {
|
void NimBLEAdvertising::setServiceData(const NimBLEUUID &uuid, const std::string &data) {
|
||||||
switch (uuid.bitSize()) {
|
switch (uuid.bitSize()) {
|
||||||
case 16: {
|
case 16: {
|
||||||
m_svcData16.assign((uint8_t*)&uuid.getNative()->u16.value, (uint8_t*)&uuid.getNative()->u16.value + 2);
|
std::vector<uint8_t>((uint8_t*)&uuid.getNative()->u16.value,
|
||||||
|
(uint8_t*)&uuid.getNative()->u16.value + 2).swap(m_svcData16);
|
||||||
m_svcData16.insert(m_svcData16.end(), data.begin(), data.end());
|
m_svcData16.insert(m_svcData16.end(), data.begin(), data.end());
|
||||||
m_advData.svc_data_uuid16 = (uint8_t*)&m_svcData16[0];
|
m_advData.svc_data_uuid16 = (uint8_t*)&m_svcData16[0];
|
||||||
m_advData.svc_data_uuid16_len = (data.length() > 0) ? m_svcData16.size() : 0;
|
m_advData.svc_data_uuid16_len = (data.length() > 0) ? m_svcData16.size() : 0;
|
||||||
@ -197,7 +205,8 @@ void NimBLEAdvertising::setServiceData(const NimBLEUUID &uuid, const std::string
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 32: {
|
case 32: {
|
||||||
m_svcData32.assign((uint8_t*)&uuid.getNative()->u32.value, (uint8_t*)&uuid.getNative()->u32.value + 4);
|
std::vector<uint8_t>((uint8_t*)&uuid.getNative()->u32.value,
|
||||||
|
(uint8_t*)&uuid.getNative()->u32.value + 4).swap(m_svcData32);
|
||||||
m_svcData32.insert(m_svcData32.end(), data.begin(), data.end());
|
m_svcData32.insert(m_svcData32.end(), data.begin(), data.end());
|
||||||
m_advData.svc_data_uuid32 = (uint8_t*)&m_svcData32[0];
|
m_advData.svc_data_uuid32 = (uint8_t*)&m_svcData32[0];
|
||||||
m_advData.svc_data_uuid32_len = (data.length() > 0) ? m_svcData32.size() : 0;
|
m_advData.svc_data_uuid32_len = (data.length() > 0) ? m_svcData32.size() : 0;
|
||||||
@ -205,7 +214,8 @@ void NimBLEAdvertising::setServiceData(const NimBLEUUID &uuid, const std::string
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 128: {
|
case 128: {
|
||||||
m_svcData128.assign(uuid.getNative()->u128.value, uuid.getNative()->u128.value + 16);
|
std::vector<uint8_t>(uuid.getNative()->u128.value,
|
||||||
|
uuid.getNative()->u128.value + 16).swap(m_svcData128);
|
||||||
m_svcData128.insert(m_svcData128.end(), data.begin(), data.end());
|
m_svcData128.insert(m_svcData128.end(), data.begin(), data.end());
|
||||||
m_advData.svc_data_uuid128 = (uint8_t*)&m_svcData128[0];
|
m_advData.svc_data_uuid128 = (uint8_t*)&m_svcData128[0];
|
||||||
m_advData.svc_data_uuid128_len = (data.length() > 0) ? m_svcData128.size() : 0;
|
m_advData.svc_data_uuid128_len = (data.length() > 0) ? m_svcData128.size() : 0;
|
||||||
@ -402,7 +412,7 @@ void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertiseme
|
|||||||
* @param [in] dirAddr The address of a peer to directly advertise to.
|
* @param [in] dirAddr The address of a peer to directly advertise to.
|
||||||
* @return True if advertising started successfully.
|
* @return True if advertising started successfully.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdvertising *pAdv), NimBLEAddress* dirAddr) {
|
bool NimBLEAdvertising::start(uint32_t duration, advCompleteCB_t advCompleteCB, NimBLEAddress* dirAddr) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> Advertising start: customAdvData: %d, customScanResponseData: %d",
|
NIMBLE_LOGD(LOG_TAG, ">> Advertising start: customAdvData: %d, customScanResponseData: %d",
|
||||||
m_customAdvData, m_customScanResponseData);
|
m_customAdvData, m_customScanResponseData);
|
||||||
|
|
||||||
@ -490,8 +500,8 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||||||
if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc((void*)m_advData.uuids16,
|
if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc((void*)m_advData.uuids16,
|
||||||
(m_advData.num_uuids16 + 1) * sizeof(ble_uuid16_t))))
|
(m_advData.num_uuids16 + 1) * sizeof(ble_uuid16_t))))
|
||||||
{
|
{
|
||||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
NIMBLE_LOGE(LOG_TAG, "Error, no mem");
|
||||||
abort();
|
return false;
|
||||||
}
|
}
|
||||||
memcpy((void*)&m_advData.uuids16[m_advData.num_uuids16],
|
memcpy((void*)&m_advData.uuids16[m_advData.num_uuids16],
|
||||||
&it.getNative()->u16, sizeof(ble_uuid16_t));
|
&it.getNative()->u16, sizeof(ble_uuid16_t));
|
||||||
@ -509,8 +519,8 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||||||
if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc((void*)m_advData.uuids32,
|
if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc((void*)m_advData.uuids32,
|
||||||
(m_advData.num_uuids32 + 1) * sizeof(ble_uuid32_t))))
|
(m_advData.num_uuids32 + 1) * sizeof(ble_uuid32_t))))
|
||||||
{
|
{
|
||||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
NIMBLE_LOGE(LOG_TAG, "Error, no mem");
|
||||||
abort();
|
return false;
|
||||||
}
|
}
|
||||||
memcpy((void*)&m_advData.uuids32[m_advData.num_uuids32],
|
memcpy((void*)&m_advData.uuids32[m_advData.num_uuids32],
|
||||||
&it.getNative()->u32, sizeof(ble_uuid32_t));
|
&it.getNative()->u32, sizeof(ble_uuid32_t));
|
||||||
@ -528,8 +538,8 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||||||
if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc((void*)m_advData.uuids128,
|
if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc((void*)m_advData.uuids128,
|
||||||
(m_advData.num_uuids128 + 1) * sizeof(ble_uuid128_t))))
|
(m_advData.num_uuids128 + 1) * sizeof(ble_uuid128_t))))
|
||||||
{
|
{
|
||||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
NIMBLE_LOGE(LOG_TAG, "Error, no mem");
|
||||||
abort();
|
return false;
|
||||||
}
|
}
|
||||||
memcpy((void*)&m_advData.uuids128[m_advData.num_uuids128],
|
memcpy((void*)&m_advData.uuids128[m_advData.num_uuids128],
|
||||||
&it.getNative()->u128, sizeof(ble_uuid128_t));
|
&it.getNative()->u128, sizeof(ble_uuid128_t));
|
||||||
@ -762,7 +772,7 @@ int NimBLEAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
case BLE_HS_EOS:
|
case BLE_HS_EOS:
|
||||||
case BLE_HS_ECONTROLLER:
|
case BLE_HS_ECONTROLLER:
|
||||||
case BLE_HS_ENOTSYNCED:
|
case BLE_HS_ENOTSYNCED:
|
||||||
NIMBLE_LOGC(LOG_TAG, "host reset, rc=%d", event->adv_complete.reason);
|
NIMBLE_LOGE(LOG_TAG, "host reset, rc=%d", event->adv_complete.reason);
|
||||||
NimBLEDevice::onReset(event->adv_complete.reason);
|
NimBLEDevice::onReset(event->adv_complete.reason);
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
@ -800,9 +810,6 @@ void NimBLEAdvertisementData::addData(char * data, size_t length) {
|
|||||||
/**
|
/**
|
||||||
* @brief Set the appearance.
|
* @brief Set the appearance.
|
||||||
* @param [in] appearance The appearance code value.
|
* @param [in] appearance The appearance code value.
|
||||||
*
|
|
||||||
* See also:
|
|
||||||
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml
|
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::setAppearance(uint16_t appearance) {
|
void NimBLEAdvertisementData::setAppearance(uint16_t appearance) {
|
||||||
char cdata[2];
|
char cdata[2];
|
||||||
@ -1069,4 +1076,12 @@ std::string NimBLEAdvertisementData::getPayload() {
|
|||||||
return m_payload;
|
return m_payload;
|
||||||
} // getPayload
|
} // getPayload
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear the advertisement data for reuse.
|
||||||
|
*/
|
||||||
|
void NimBLEAdvertisementData::clearData() {
|
||||||
|
m_payload.clear();
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
#include "NimBLEUUID.h"
|
#include "NimBLEUUID.h"
|
||||||
#include "NimBLEAddress.h"
|
#include "NimBLEAddress.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/* COMPATIBILITY - DO NOT USE */
|
/* COMPATIBILITY - DO NOT USE */
|
||||||
@ -44,6 +45,9 @@
|
|||||||
#define ESP_BLE_ADV_FLAG_NON_LIMIT_DISC (0x00 )
|
#define ESP_BLE_ADV_FLAG_NON_LIMIT_DISC (0x00 )
|
||||||
/* ************************* */
|
/* ************************* */
|
||||||
|
|
||||||
|
class NimBLEAdvertising;
|
||||||
|
|
||||||
|
typedef std::function<void(NimBLEAdvertising*)> advCompleteCB_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Advertisement data set by the programmer to be published by the %BLE server.
|
* @brief Advertisement data set by the programmer to be published by the %BLE server.
|
||||||
@ -72,6 +76,7 @@ public:
|
|||||||
void addTxPower();
|
void addTxPower();
|
||||||
void setPreferredParams(uint16_t min, uint16_t max);
|
void setPreferredParams(uint16_t min, uint16_t max);
|
||||||
std::string getPayload(); // Retrieve the current advert payload.
|
std::string getPayload(); // Retrieve the current advert payload.
|
||||||
|
void clearData(); // Clear the advertisement data.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NimBLEAdvertising;
|
friend class NimBLEAdvertising;
|
||||||
@ -92,7 +97,8 @@ public:
|
|||||||
void addServiceUUID(const NimBLEUUID &serviceUUID);
|
void addServiceUUID(const NimBLEUUID &serviceUUID);
|
||||||
void addServiceUUID(const char* serviceUUID);
|
void addServiceUUID(const char* serviceUUID);
|
||||||
void removeServiceUUID(const NimBLEUUID &serviceUUID);
|
void removeServiceUUID(const NimBLEUUID &serviceUUID);
|
||||||
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr, NimBLEAddress* dirAddr = nullptr);
|
bool start(uint32_t duration = 0, advCompleteCB_t advCompleteCB = nullptr, NimBLEAddress* dirAddr = nullptr);
|
||||||
|
void removeServices();
|
||||||
bool stop();
|
bool stop();
|
||||||
void setAppearance(uint16_t appearance);
|
void setAppearance(uint16_t appearance);
|
||||||
void setName(const std::string &name);
|
void setName(const std::string &name);
|
||||||
@ -129,7 +135,7 @@ private:
|
|||||||
bool m_customScanResponseData;
|
bool m_customScanResponseData;
|
||||||
bool m_scanResp;
|
bool m_scanResp;
|
||||||
bool m_advDataSet;
|
bool m_advDataSet;
|
||||||
void (*m_advCompCB)(NimBLEAdvertising *pAdv);
|
advCompleteCB_t m_advCompCB{nullptr};
|
||||||
uint8_t m_slaveItvl[4];
|
uint8_t m_slaveItvl[4];
|
||||||
uint32_t m_duration;
|
uint32_t m_duration;
|
||||||
std::vector<uint8_t> m_svcData16;
|
std::vector<uint8_t> m_svcData16;
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
#ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
#ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||||
# define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
|
# define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
|
||||||
@ -41,7 +42,6 @@
|
|||||||
# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512
|
# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Used to determine if the type passed to a template has a c_str() and length() method. */
|
/* Used to determine if the type passed to a template has a c_str() and length() method. */
|
||||||
template <typename T, typename = void, typename = void>
|
template <typename T, typename = void, typename = void>
|
||||||
struct Has_c_str_len : std::false_type {};
|
struct Has_c_str_len : std::false_type {};
|
||||||
@ -266,7 +266,8 @@ public:
|
|||||||
|
|
||||||
/** @brief Subscript operator */
|
/** @brief Subscript operator */
|
||||||
uint8_t operator [](int pos) const {
|
uint8_t operator [](int pos) const {
|
||||||
assert(pos < m_attr_len && "out of range"); return m_attr_value[pos]; }
|
NIMBLE_CPP_DEBUG_ASSERT(pos < m_attr_len);
|
||||||
|
return m_attr_value[pos]; }
|
||||||
|
|
||||||
/** @brief Operator; Get the value as a std::vector<uint8_t>. */
|
/** @brief Operator; Get the value as a std::vector<uint8_t>. */
|
||||||
operator std::vector<uint8_t>() const {
|
operator std::vector<uint8_t>() const {
|
||||||
@ -311,7 +312,7 @@ public:
|
|||||||
|
|
||||||
inline NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len) {
|
inline NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len) {
|
||||||
m_attr_value = (uint8_t*)calloc(init_len + 1, 1);
|
m_attr_value = (uint8_t*)calloc(init_len + 1, 1);
|
||||||
assert(m_attr_value && "No Mem");
|
NIMBLE_CPP_DEBUG_ASSERT(m_attr_value);
|
||||||
m_attr_max_len = std::min(BLE_ATT_ATTR_MAX_LEN, (int)max_len);
|
m_attr_max_len = std::min(BLE_ATT_ATTR_MAX_LEN, (int)max_len);
|
||||||
m_attr_len = 0;
|
m_attr_len = 0;
|
||||||
m_capacity = init_len;
|
m_capacity = init_len;
|
||||||
@ -354,7 +355,7 @@ inline NimBLEAttValue& NimBLEAttValue::operator =(const NimBLEAttValue & source)
|
|||||||
|
|
||||||
inline void NimBLEAttValue::deepCopy(const NimBLEAttValue & source) {
|
inline void NimBLEAttValue::deepCopy(const NimBLEAttValue & source) {
|
||||||
uint8_t* res = (uint8_t*)realloc( m_attr_value, source.m_capacity + 1);
|
uint8_t* res = (uint8_t*)realloc( m_attr_value, source.m_capacity + 1);
|
||||||
assert(res && "deepCopy: realloc failed");
|
NIMBLE_CPP_DEBUG_ASSERT(res);
|
||||||
|
|
||||||
ble_npl_hw_enter_critical();
|
ble_npl_hw_enter_critical();
|
||||||
m_attr_value = res;
|
m_attr_value = res;
|
||||||
@ -389,7 +390,7 @@ inline bool NimBLEAttValue::setValue(const uint8_t *value, uint16_t len) {
|
|||||||
res = (uint8_t*)realloc(m_attr_value, (len + 1));
|
res = (uint8_t*)realloc(m_attr_value, (len + 1));
|
||||||
m_capacity = len;
|
m_capacity = len;
|
||||||
}
|
}
|
||||||
assert(res && "setValue: realloc failed");
|
NIMBLE_CPP_DEBUG_ASSERT(res);
|
||||||
|
|
||||||
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||||
time_t t = time(nullptr);
|
time_t t = time(nullptr);
|
||||||
@ -424,7 +425,7 @@ inline NimBLEAttValue& NimBLEAttValue::append(const uint8_t *value, uint16_t len
|
|||||||
res = (uint8_t*)realloc(m_attr_value, (new_len + 1));
|
res = (uint8_t*)realloc(m_attr_value, (new_len + 1));
|
||||||
m_capacity = new_len;
|
m_capacity = new_len;
|
||||||
}
|
}
|
||||||
assert(res && "append: realloc failed");
|
NIMBLE_CPP_DEBUG_ASSERT(res);
|
||||||
|
|
||||||
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||||
time_t t = time(nullptr);
|
time_t t = time(nullptr);
|
||||||
|
|||||||
@ -87,9 +87,7 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint3
|
|||||||
*/
|
*/
|
||||||
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) {
|
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) {
|
||||||
NimBLEDescriptor* pDescriptor = nullptr;
|
NimBLEDescriptor* pDescriptor = nullptr;
|
||||||
if(uuid == NimBLEUUID(uint16_t(0x2902))) {
|
if (uuid == NimBLEUUID(uint16_t(0x2904))) {
|
||||||
assert(0 && "0x2902 descriptors cannot be manually created");
|
|
||||||
} else if (uuid == NimBLEUUID(uint16_t(0x2904))) {
|
|
||||||
pDescriptor = new NimBLE2904(this);
|
pDescriptor = new NimBLE2904(this);
|
||||||
} else {
|
} else {
|
||||||
pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this);
|
pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this);
|
||||||
@ -266,7 +264,7 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
|
|||||||
NIMBLE_LOGW(LOG_TAG, "Conn_handle (%d) is above the maximum value (%d)", conn_handle, BLE_HCI_LE_CONN_HANDLE_MAX);
|
NIMBLE_LOGW(LOG_TAG, "Conn_handle (%d) is above the maximum value (%d)", conn_handle, BLE_HCI_LE_CONN_HANDLE_MAX);
|
||||||
return BLE_ATT_ERR_INVALID_HANDLE;
|
return BLE_ATT_ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ble_uuid_t *uuid;
|
const ble_uuid_t *uuid;
|
||||||
int rc;
|
int rc;
|
||||||
NimBLEConnInfo peerInfo;
|
NimBLEConnInfo peerInfo;
|
||||||
@ -279,12 +277,12 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
|
|||||||
if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){
|
if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){
|
||||||
switch(ctxt->op) {
|
switch(ctxt->op) {
|
||||||
case BLE_GATT_ACCESS_OP_READ_CHR: {
|
case BLE_GATT_ACCESS_OP_READ_CHR: {
|
||||||
rc = ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||||
assert(rc == 0);
|
|
||||||
|
|
||||||
// If the packet header is only 8 bytes this is a follow up of a long read
|
// If the packet header is only 8 bytes this is a follow up of a long read
|
||||||
// so we don't want to call the onRead() callback again.
|
// so we don't want to call the onRead() callback again.
|
||||||
if(ctxt->om->om_pkthdr_len > 8 ||
|
if(ctxt->om->om_pkthdr_len > 8 ||
|
||||||
|
conn_handle == BLE_HS_CONN_HANDLE_NONE ||
|
||||||
pCharacteristic->m_value.size() <= (ble_att_mtu(peerInfo.m_desc.conn_handle) - 3)) {
|
pCharacteristic->m_value.size() <= (ble_att_mtu(peerInfo.m_desc.conn_handle) - 3)) {
|
||||||
pCharacteristic->m_pCallbacks->onRead(pCharacteristic, peerInfo);
|
pCharacteristic->m_pCallbacks->onRead(pCharacteristic, peerInfo);
|
||||||
}
|
}
|
||||||
@ -316,8 +314,8 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
|
|||||||
len += next->om_len;
|
len += next->om_len;
|
||||||
next = SLIST_NEXT(next, om_next);
|
next = SLIST_NEXT(next, om_next);
|
||||||
}
|
}
|
||||||
rc = ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
|
||||||
assert(rc == 0);
|
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||||
pCharacteristic->setValue(buf, len);
|
pCharacteristic->setValue(buf, len);
|
||||||
pCharacteristic->m_pCallbacks->onWrite(pCharacteristic, peerInfo);
|
pCharacteristic->m_pCallbacks->onWrite(pCharacteristic, peerInfo);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -111,7 +111,7 @@ NimBLEClient::~NimBLEClient() {
|
|||||||
*/
|
*/
|
||||||
void NimBLEClient::dcTimerCb(ble_npl_event *event) {
|
void NimBLEClient::dcTimerCb(ble_npl_event *event) {
|
||||||
/* NimBLEClient *pClient = (NimBLEClient*)event->arg;
|
/* NimBLEClient *pClient = (NimBLEClient*)event->arg;
|
||||||
NIMBLE_LOGC(LOG_TAG, "Timed out disconnecting from %s - resetting host",
|
NIMBLE_LOGE(LOG_TAG, "Timed out disconnecting from %s - resetting host",
|
||||||
std::string(pClient->getPeerAddress()).c_str());
|
std::string(pClient->getPeerAddress()).c_str());
|
||||||
*/
|
*/
|
||||||
ble_hs_sched_reset(BLE_HS_ECONTROLLER);
|
ble_hs_sched_reset(BLE_HS_ECONTROLLER);
|
||||||
@ -189,7 +189,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttributes)
|
|||||||
NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
|
||||||
|
|
||||||
if(!NimBLEDevice::m_synced) {
|
if(!NimBLEDevice::m_synced) {
|
||||||
NIMBLE_LOGC(LOG_TAG, "Host reset, wait for sync.");
|
NIMBLE_LOGE(LOG_TAG, "Host reset, wait for sync.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,9 +458,6 @@ void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterva
|
|||||||
// These are not used by NimBLE at this time - Must leave at defaults
|
// These are not used by NimBLE at this time - Must leave at defaults
|
||||||
//m_pConnParams->min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units
|
//m_pConnParams->min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units
|
||||||
//m_pConnParams->max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units
|
//m_pConnParams->max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units
|
||||||
|
|
||||||
int rc = NimBLEUtils::checkConnParams(&m_pConnParams);
|
|
||||||
assert(rc == 0 && "Invalid Connection parameters");
|
|
||||||
} // setConnectionParams
|
} // setConnectionParams
|
||||||
|
|
||||||
|
|
||||||
@ -551,6 +548,66 @@ uint16_t NimBLEClient::getConnId() {
|
|||||||
return m_conn_id;
|
return m_conn_id;
|
||||||
} // getConnId
|
} // getConnId
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear the connection information for this client.
|
||||||
|
* @note This is designed to be used to reset the connection information after
|
||||||
|
* calling setConnection(), and should not be used to disconnect from a
|
||||||
|
* peer. To disconnect from a peer, use disconnect().
|
||||||
|
*/
|
||||||
|
void NimBLEClient::clearConnection() {
|
||||||
|
m_conn_id = BLE_HS_CONN_HANDLE_NONE;
|
||||||
|
m_connEstablished = false;
|
||||||
|
m_peerAddress = NimBLEAddress();
|
||||||
|
} // clearConnection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the connection information for this client.
|
||||||
|
* @param [in] connInfo The connection information.
|
||||||
|
* @return True on success.
|
||||||
|
* @note Sets the connection established flag to true.
|
||||||
|
* @note If the client is already connected to a peer, this will return false.
|
||||||
|
* @note This is designed to be used when a connection is made outside of the
|
||||||
|
* NimBLEClient class, such as when a connection is made by the
|
||||||
|
* NimBLEServer class and the client is passed the connection id. This use
|
||||||
|
* enables the GATT Server to read the name of the device that has
|
||||||
|
* connected to it.
|
||||||
|
*/
|
||||||
|
bool NimBLEClient::setConnection(NimBLEConnInfo &connInfo) {
|
||||||
|
if (isConnected() || m_connEstablished) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Already connected");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_peerAddress = connInfo.getAddress();
|
||||||
|
m_conn_id = connInfo.getConnHandle();
|
||||||
|
m_connEstablished = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} // setConnection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the connection information for this client.
|
||||||
|
* @param [in] conn_id The connection id.
|
||||||
|
* @note Sets the connection established flag to true.
|
||||||
|
* @note This is designed to be used when a connection is made outside of the
|
||||||
|
* NimBLEClient class, such as when a connection is made by the
|
||||||
|
* NimBLEServer class and the client is passed the connection id. This use
|
||||||
|
* enables the GATT Server to read the name of the device that has
|
||||||
|
* connected to it.
|
||||||
|
* @note If the client is already connected to a peer, this will return false.
|
||||||
|
* @note This will look up the peer address using the connection id.
|
||||||
|
*/
|
||||||
|
bool NimBLEClient::setConnection(uint16_t conn_id) {
|
||||||
|
// we weren't provided the peer address, look it up using ble_gap_conn_find
|
||||||
|
NimBLEConnInfo connInfo;
|
||||||
|
int rc = ble_gap_conn_find(m_conn_id, &connInfo.m_desc);
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Connection info not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setConnection(connInfo);
|
||||||
|
} // setConnection
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve the address of the peer.
|
* @brief Retrieve the address of the peer.
|
||||||
@ -945,7 +1002,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
case BLE_HS_ETIMEOUT_HCI:
|
case BLE_HS_ETIMEOUT_HCI:
|
||||||
case BLE_HS_ENOTSYNCED:
|
case BLE_HS_ENOTSYNCED:
|
||||||
case BLE_HS_EOS:
|
case BLE_HS_EOS:
|
||||||
NIMBLE_LOGC(LOG_TAG, "Disconnect - host reset, rc=%d", rc);
|
NIMBLE_LOGE(LOG_TAG, "Disconnect - host reset, rc=%d", rc);
|
||||||
NimBLEDevice::onReset(rc);
|
NimBLEDevice::onReset(rc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1111,7 +1168,11 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
{
|
{
|
||||||
NimBLEConnInfo peerInfo;
|
NimBLEConnInfo peerInfo;
|
||||||
rc = ble_gap_conn_find(event->enc_change.conn_handle, &peerInfo.m_desc);
|
rc = ble_gap_conn_find(event->enc_change.conn_handle, &peerInfo.m_desc);
|
||||||
assert(rc == 0);
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Connection info not found");
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (event->enc_change.status == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING)) {
|
if (event->enc_change.status == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING)) {
|
||||||
// Key is missing, try deleting.
|
// Key is missing, try deleting.
|
||||||
@ -1125,6 +1186,19 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
break;
|
break;
|
||||||
} //BLE_GAP_EVENT_ENC_CHANGE
|
} //BLE_GAP_EVENT_ENC_CHANGE
|
||||||
|
|
||||||
|
case BLE_GAP_EVENT_IDENTITY_RESOLVED: {
|
||||||
|
NimBLEConnInfo peerInfo;
|
||||||
|
rc = ble_gap_conn_find(event->identity_resolved.conn_handle, &peerInfo.m_desc);
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Connection info not found");
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pClient->m_pClientCallbacks->onIdentity(peerInfo);
|
||||||
|
break;
|
||||||
|
} // BLE_GAP_EVENT_IDENTITY_RESOLVED
|
||||||
|
|
||||||
case BLE_GAP_EVENT_MTU: {
|
case BLE_GAP_EVENT_MTU: {
|
||||||
if(pClient->m_conn_id != event->mtu.conn_handle){
|
if(pClient->m_conn_id != event->mtu.conn_handle){
|
||||||
return 0;
|
return 0;
|
||||||
@ -1143,20 +1217,17 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
if(pClient->m_conn_id != event->passkey.conn_handle)
|
if(pClient->m_conn_id != event->passkey.conn_handle)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (event->passkey.params.action == BLE_SM_IOACT_DISP) {
|
NimBLEConnInfo peerInfo;
|
||||||
pkey.action = event->passkey.params.action;
|
rc = ble_gap_conn_find(event->passkey.conn_handle, &peerInfo.m_desc);
|
||||||
pkey.passkey = NimBLEDevice::m_passkey; // This is the passkey to be entered on peer
|
if (rc != 0) {
|
||||||
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
NIMBLE_LOGE(LOG_TAG, "Connection info not found");
|
||||||
NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc);
|
rc = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
|
if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %" PRIu32, event->passkey.params.numcmp);
|
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %" PRIu32, event->passkey.params.numcmp);
|
||||||
pkey.action = event->passkey.params.action;
|
pClient->m_pClientCallbacks->onConfirmPIN(peerInfo, event->passkey.params.numcmp);
|
||||||
pkey.numcmp_accept = pClient->m_pClientCallbacks->onConfirmPIN(event->passkey.params.numcmp);
|
|
||||||
|
|
||||||
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc);
|
|
||||||
|
|
||||||
//TODO: Handle out of band pairing
|
//TODO: Handle out of band pairing
|
||||||
} else if (event->passkey.params.action == BLE_SM_IOACT_OOB) {
|
} else if (event->passkey.params.action == BLE_SM_IOACT_OOB) {
|
||||||
static uint8_t tem_oob[16] = {0};
|
static uint8_t tem_oob[16] = {0};
|
||||||
@ -1169,12 +1240,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
////////
|
////////
|
||||||
} else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) {
|
} else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "Enter the passkey");
|
NIMBLE_LOGD(LOG_TAG, "Enter the passkey");
|
||||||
pkey.action = event->passkey.params.action;
|
pClient->m_pClientCallbacks->onPassKeyEntry(peerInfo);
|
||||||
pkey.passkey = pClient->m_pClientCallbacks->onPassKeyRequest();
|
|
||||||
|
|
||||||
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc);
|
|
||||||
|
|
||||||
} else if (event->passkey.params.action == BLE_SM_IOACT_NONE) {
|
} else if (event->passkey.params.action == BLE_SM_IOACT_NONE) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "No passkey action required");
|
NIMBLE_LOGD(LOG_TAG, "No passkey action required");
|
||||||
}
|
}
|
||||||
@ -1261,17 +1327,22 @@ bool NimBLEClientCallbacks::onConnParamsUpdateRequest(NimBLEClient* pClient, con
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t NimBLEClientCallbacks::onPassKeyRequest(){
|
void NimBLEClientCallbacks::onPassKeyEntry(const NimBLEConnInfo& connInfo){
|
||||||
NIMBLE_LOGD("NimBLEClientCallbacks", "onPassKeyRequest: default: 123456");
|
NIMBLE_LOGD("NimBLEClientCallbacks", "onPassKeyEntry: default: 123456");
|
||||||
return 123456;
|
NimBLEDevice::injectPassKey(connInfo, 123456);
|
||||||
}
|
} //onPassKeyEntry
|
||||||
|
|
||||||
void NimBLEClientCallbacks::onAuthenticationComplete(NimBLEConnInfo& peerInfo){
|
void NimBLEClientCallbacks::onAuthenticationComplete(const NimBLEConnInfo& connInfo){
|
||||||
NIMBLE_LOGD("NimBLEClientCallbacks", "onAuthenticationComplete: default");
|
NIMBLE_LOGD("NimBLEClientCallbacks", "onAuthenticationComplete: default");
|
||||||
}
|
}
|
||||||
bool NimBLEClientCallbacks::onConfirmPIN(uint32_t pin){
|
|
||||||
|
void NimBLEClientCallbacks::onIdentity(const NimBLEConnInfo& connInfo){
|
||||||
|
NIMBLE_LOGD("NimBLEClientCallbacks", "onIdentity: default");
|
||||||
|
} // onIdentity
|
||||||
|
|
||||||
|
void NimBLEClientCallbacks::onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pin){
|
||||||
NIMBLE_LOGD("NimBLEClientCallbacks", "onConfirmPIN: default: true");
|
NIMBLE_LOGD("NimBLEClientCallbacks", "onConfirmPIN: default: true");
|
||||||
return true;
|
NimBLEDevice::injectConfirmPIN(connInfo, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
|
||||||
|
|||||||
@ -61,6 +61,9 @@ public:
|
|||||||
bool deleteCallbacks = true);
|
bool deleteCallbacks = true);
|
||||||
std::string toString();
|
std::string toString();
|
||||||
uint16_t getConnId();
|
uint16_t getConnId();
|
||||||
|
void clearConnection();
|
||||||
|
bool setConnection(NimBLEConnInfo &conn_info);
|
||||||
|
bool setConnection(uint16_t conn_id);
|
||||||
uint16_t getMTU();
|
uint16_t getMTU();
|
||||||
bool secureConnection();
|
bool secureConnection();
|
||||||
void setConnectTimeout(uint32_t timeout);
|
void setConnectTimeout(uint32_t timeout);
|
||||||
@ -144,23 +147,29 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when server requests a passkey for pairing.
|
* @brief Called when server requests a passkey for pairing.
|
||||||
* @return The passkey to be sent to the server.
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.
|
||||||
*/
|
*/
|
||||||
virtual uint32_t onPassKeyRequest();
|
virtual void onPassKeyEntry(const NimBLEConnInfo& connInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when the pairing procedure is complete.
|
* @brief Called when the pairing procedure is complete.
|
||||||
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.\n
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.\n
|
||||||
* This can be used to check the status of the connection encryption/pairing.
|
* This can be used to check the status of the connection encryption/pairing.
|
||||||
*/
|
*/
|
||||||
virtual void onAuthenticationComplete(NimBLEConnInfo& connInfo);
|
virtual void onAuthenticationComplete(const NimBLEConnInfo& connInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when using numeric comparision for pairing.
|
* @brief Called when using numeric comparision for pairing.
|
||||||
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.
|
||||||
* @param [in] pin The pin to compare with the server.
|
* @param [in] pin The pin to compare with the server.
|
||||||
* @return True to accept the pin.
|
|
||||||
*/
|
*/
|
||||||
virtual bool onConfirmPIN(uint32_t pin);
|
virtual void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pin);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when the peer identity address is resolved.
|
||||||
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance with information
|
||||||
|
*/
|
||||||
|
virtual void onIdentity(const NimBLEConnInfo& connInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
|
||||||
|
|||||||
@ -12,47 +12,47 @@ friend class NimBLEClient;
|
|||||||
friend class NimBLECharacteristic;
|
friend class NimBLECharacteristic;
|
||||||
friend class NimBLEDescriptor;
|
friend class NimBLEDescriptor;
|
||||||
|
|
||||||
ble_gap_conn_desc m_desc;
|
ble_gap_conn_desc m_desc{};
|
||||||
NimBLEConnInfo() { m_desc = {}; }
|
NimBLEConnInfo(){};
|
||||||
NimBLEConnInfo(ble_gap_conn_desc desc) { m_desc = desc; }
|
NimBLEConnInfo(ble_gap_conn_desc desc) { m_desc = desc; }
|
||||||
public:
|
public:
|
||||||
/** @brief Gets the over-the-air address of the connected peer */
|
/** @brief Gets the over-the-air address of the connected peer */
|
||||||
NimBLEAddress getAddress() { return NimBLEAddress(m_desc.peer_ota_addr); }
|
NimBLEAddress getAddress() const { return NimBLEAddress(m_desc.peer_ota_addr); }
|
||||||
|
|
||||||
/** @brief Gets the ID address of the connected peer */
|
/** @brief Gets the ID address of the connected peer */
|
||||||
NimBLEAddress getIdAddress() { return NimBLEAddress(m_desc.peer_id_addr); }
|
NimBLEAddress getIdAddress() const { return NimBLEAddress(m_desc.peer_id_addr); }
|
||||||
|
|
||||||
/** @brief Gets the connection handle of the connected peer */
|
/** @brief Gets the connection handle (also known as the connection id) of the connected peer */
|
||||||
uint16_t getConnHandle() { return m_desc.conn_handle; }
|
uint16_t getConnHandle() const { return m_desc.conn_handle; }
|
||||||
|
|
||||||
/** @brief Gets the connection interval for this connection (in 1.25ms units) */
|
/** @brief Gets the connection interval for this connection (in 1.25ms units) */
|
||||||
uint16_t getConnInterval() { return m_desc.conn_itvl; }
|
uint16_t getConnInterval() const { return m_desc.conn_itvl; }
|
||||||
|
|
||||||
/** @brief Gets the supervision timeout for this connection (in 10ms units) */
|
/** @brief Gets the supervision timeout for this connection (in 10ms units) */
|
||||||
uint16_t getConnTimeout() { return m_desc.supervision_timeout; }
|
uint16_t getConnTimeout() const { return m_desc.supervision_timeout; }
|
||||||
|
|
||||||
/** @brief Gets the allowable latency for this connection (unit = number of intervals) */
|
/** @brief Gets the allowable latency for this connection (unit = number of intervals) */
|
||||||
uint16_t getConnLatency() { return m_desc.conn_latency; }
|
uint16_t getConnLatency() const { return m_desc.conn_latency; }
|
||||||
|
|
||||||
/** @brief Gets the maximum transmission unit size for this connection (in bytes) */
|
/** @brief Gets the maximum transmission unit size for this connection (in bytes) */
|
||||||
uint16_t getMTU() { return ble_att_mtu(m_desc.conn_handle); }
|
uint16_t getMTU() const { return ble_att_mtu(m_desc.conn_handle); }
|
||||||
|
|
||||||
/** @brief Check if we are in the master role in this connection */
|
/** @brief Check if we are in the master role in this connection */
|
||||||
bool isMaster() { return (m_desc.role == BLE_GAP_ROLE_MASTER); }
|
bool isMaster() const { return (m_desc.role == BLE_GAP_ROLE_MASTER); }
|
||||||
|
|
||||||
/** @brief Check if we are in the slave role in this connection */
|
/** @brief Check if we are in the slave role in this connection */
|
||||||
bool isSlave() { return (m_desc.role == BLE_GAP_ROLE_SLAVE); }
|
bool isSlave() const { return (m_desc.role == BLE_GAP_ROLE_SLAVE); }
|
||||||
|
|
||||||
/** @brief Check if we are connected to a bonded peer */
|
/** @brief Check if we are connected to a bonded peer */
|
||||||
bool isBonded() { return (m_desc.sec_state.bonded == 1); }
|
bool isBonded() const { return (m_desc.sec_state.bonded == 1); }
|
||||||
|
|
||||||
/** @brief Check if the connection in encrypted */
|
/** @brief Check if the connection in encrypted */
|
||||||
bool isEncrypted() { return (m_desc.sec_state.encrypted == 1); }
|
bool isEncrypted() const { return (m_desc.sec_state.encrypted == 1); }
|
||||||
|
|
||||||
/** @brief Check if the the connection has been authenticated */
|
/** @brief Check if the the connection has been authenticated */
|
||||||
bool isAuthenticated() { return (m_desc.sec_state.authenticated == 1); }
|
bool isAuthenticated() const { return (m_desc.sec_state.authenticated == 1); }
|
||||||
|
|
||||||
/** @brief Gets the key size used to encrypt the connection */
|
/** @brief Gets the key size used to encrypt the connection */
|
||||||
uint8_t getSecKeySize() { return m_desc.sec_state.key_size; }
|
uint8_t getSecKeySize() const { return m_desc.sec_state.key_size; }
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -55,7 +55,14 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_
|
|||||||
m_pCharacteristic = pCharacteristic;
|
m_pCharacteristic = pCharacteristic;
|
||||||
m_pCallbacks = &defaultCallbacks; // No initial callback.
|
m_pCallbacks = &defaultCallbacks; // No initial callback.
|
||||||
m_properties = 0;
|
m_properties = 0;
|
||||||
m_removed = 0;
|
|
||||||
|
// Check if this is the client configuration descriptor and set to removed if true.
|
||||||
|
if (uuid == NimBLEUUID((uint16_t)0x2902)) {
|
||||||
|
NIMBLE_LOGW(LOG_TAG, "Manually created 2902 descriptor has no functionality; please remove.");
|
||||||
|
m_removed = 1;
|
||||||
|
} else {
|
||||||
|
m_removed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (properties & BLE_GATT_CHR_F_READ) { // convert uint16_t properties to uint8_t
|
if (properties & BLE_GATT_CHR_F_READ) { // convert uint16_t properties to uint8_t
|
||||||
m_properties |= BLE_ATT_F_READ;
|
m_properties |= BLE_ATT_F_READ;
|
||||||
@ -155,7 +162,7 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
|||||||
|
|
||||||
const ble_uuid_t *uuid;
|
const ble_uuid_t *uuid;
|
||||||
int rc;
|
int rc;
|
||||||
NimBLEConnInfo peerInfo;
|
NimBLEConnInfo peerInfo{};
|
||||||
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Descriptor %s %s event", pDescriptor->getUUID().toString().c_str(),
|
NIMBLE_LOGD(LOG_TAG, "Descriptor %s %s event", pDescriptor->getUUID().toString().c_str(),
|
||||||
@ -165,12 +172,12 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
|||||||
if(ble_uuid_cmp(uuid, &pDescriptor->getUUID().getNative()->u) == 0){
|
if(ble_uuid_cmp(uuid, &pDescriptor->getUUID().getNative()->u) == 0){
|
||||||
switch(ctxt->op) {
|
switch(ctxt->op) {
|
||||||
case BLE_GATT_ACCESS_OP_READ_DSC: {
|
case BLE_GATT_ACCESS_OP_READ_DSC: {
|
||||||
rc = ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||||
assert(rc == 0);
|
|
||||||
|
|
||||||
// If the packet header is only 8 bytes this is a follow up of a long read
|
// If the packet header is only 8 bytes this is a follow up of a long read
|
||||||
// so we don't want to call the onRead() callback again.
|
// so we don't want to call the onRead() callback again.
|
||||||
if(ctxt->om->om_pkthdr_len > 8 ||
|
if(ctxt->om->om_pkthdr_len > 8 ||
|
||||||
|
conn_handle == BLE_HS_CONN_HANDLE_NONE ||
|
||||||
pDescriptor->m_value.size() <= (ble_att_mtu(peerInfo.getConnHandle()) - 3)) {
|
pDescriptor->m_value.size() <= (ble_att_mtu(peerInfo.getConnHandle()) - 3)) {
|
||||||
pDescriptor->m_pCallbacks->onRead(pDescriptor, peerInfo);
|
pDescriptor->m_pCallbacks->onRead(pDescriptor, peerInfo);
|
||||||
}
|
}
|
||||||
@ -182,11 +189,9 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case BLE_GATT_ACCESS_OP_WRITE_DSC: {
|
case BLE_GATT_ACCESS_OP_WRITE_DSC: {
|
||||||
rc = ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||||
assert(rc == 0);
|
|
||||||
|
|
||||||
uint16_t att_max_len = pDescriptor->m_value.max_size();
|
uint16_t att_max_len = pDescriptor->m_value.max_size();
|
||||||
|
|
||||||
if (ctxt->om->om_len > att_max_len) {
|
if (ctxt->om->om_len > att_max_len) {
|
||||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -299,7 +299,7 @@ size_t NimBLEDevice::getClientListSize() {
|
|||||||
/**
|
/**
|
||||||
* @brief Get a reference to a client by connection ID.
|
* @brief Get a reference to a client by connection ID.
|
||||||
* @param [in] conn_id The client connection ID to search for.
|
* @param [in] conn_id The client connection ID to search for.
|
||||||
* @return A pointer to the client object with the spcified connection ID.
|
* @return A pointer to the client object with the specified connection ID or nullptr.
|
||||||
*/
|
*/
|
||||||
/* STATIC */
|
/* STATIC */
|
||||||
NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) {
|
NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) {
|
||||||
@ -308,7 +308,7 @@ NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) {
|
|||||||
return (*it);
|
return (*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(0);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} // getClientByID
|
} // getClientByID
|
||||||
|
|
||||||
@ -444,12 +444,13 @@ int NimBLEDevice::getPower() {
|
|||||||
*/
|
*/
|
||||||
/* STATIC*/
|
/* STATIC*/
|
||||||
NimBLEAddress NimBLEDevice::getAddress() {
|
NimBLEAddress NimBLEDevice::getAddress() {
|
||||||
ble_addr_t addr = {BLE_ADDR_PUBLIC, 0};
|
ble_addr_t addr = {m_own_addr_type, 0};
|
||||||
|
|
||||||
if(BLE_HS_ENOADDR == ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)) {
|
if(BLE_HS_ENOADDR == ble_hs_id_copy_addr(m_own_addr_type, addr.val, NULL)) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "Public address not found, checking random");
|
// NIMBLE_LOGD(LOG_TAG, "Public address not found, checking random");
|
||||||
addr.type = BLE_ADDR_RANDOM;
|
// addr.type = BLE_ADDR_RANDOM;
|
||||||
ble_hs_id_copy_addr(BLE_ADDR_RANDOM, addr.val, NULL);
|
// ble_hs_id_copy_addr(BLE_ADDR_RANDOM, addr.val, NULL);
|
||||||
|
return NimBLEAddress(); // return blank to report error
|
||||||
}
|
}
|
||||||
|
|
||||||
return NimBLEAddress(addr);
|
return NimBLEAddress(addr);
|
||||||
@ -567,10 +568,16 @@ int NimBLEDevice::getNumBonds() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deletes all bonding information.
|
* @brief Deletes all bonding information.
|
||||||
|
* @returns true on success, false on failure.
|
||||||
*/
|
*/
|
||||||
/*STATIC*/
|
/*STATIC*/
|
||||||
void NimBLEDevice::deleteAllBonds() {
|
bool NimBLEDevice::deleteAllBonds() {
|
||||||
ble_store_clear();
|
int rc = ble_store_clear();
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Failed to delete all bonds; rc=%d", rc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -685,6 +692,7 @@ bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) {
|
|||||||
int rc = ble_gap_wl_set(&wlVec[0], wlVec.size());
|
int rc = ble_gap_wl_set(&wlVec[0], wlVec.size());
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Failed adding to whitelist rc=%d", rc);
|
NIMBLE_LOGE(LOG_TAG, "Failed adding to whitelist rc=%d", rc);
|
||||||
|
m_whiteList.pop_back();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,7 +779,7 @@ void NimBLEDevice::onReset(int reason)
|
|||||||
|
|
||||||
m_synced = false;
|
m_synced = false;
|
||||||
|
|
||||||
NIMBLE_LOGC(LOG_TAG, "Resetting state; reason=%d, %s", reason,
|
NIMBLE_LOGE(LOG_TAG, "Resetting state; reason=%d, %s", reason,
|
||||||
NimBLEUtils::returnCodeToString(reason));
|
NimBLEUtils::returnCodeToString(reason));
|
||||||
|
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
@ -799,7 +807,10 @@ void NimBLEDevice::onSync(void)
|
|||||||
|
|
||||||
/* Make sure we have proper identity address set (public preferred) */
|
/* Make sure we have proper identity address set (public preferred) */
|
||||||
int rc = ble_hs_util_ensure_addr(0);
|
int rc = ble_hs_util_ensure_addr(0);
|
||||||
assert(rc == 0);
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "error ensuring address; rc=%d", rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef ESP_PLATFORM
|
#ifndef ESP_PLATFORM
|
||||||
rc = ble_hs_id_infer_auto(m_own_addr_type, &m_own_addr_type);
|
rc = ble_hs_id_infer_auto(m_own_addr_type, &m_own_addr_type);
|
||||||
@ -871,9 +882,11 @@ void NimBLEDevice::init(const std::string &deviceName) {
|
|||||||
|
|
||||||
ESP_ERROR_CHECK(errRc);
|
ESP_ERROR_CHECK(errRc);
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) | !defined(CONFIG_NIMBLE_CPP_IDF)
|
||||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||||
# if defined (CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
# if defined (CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
bt_cfg.bluetooth_mode = ESP_BT_MODE_BLE;
|
bt_cfg.bluetooth_mode = ESP_BT_MODE_BLE;
|
||||||
@ -902,14 +915,16 @@ void NimBLEDevice::init(const std::string &deviceName) {
|
|||||||
ble_hs_cfg.sm_bonding = 0;
|
ble_hs_cfg.sm_bonding = 0;
|
||||||
ble_hs_cfg.sm_mitm = 0;
|
ble_hs_cfg.sm_mitm = 0;
|
||||||
ble_hs_cfg.sm_sc = 1;
|
ble_hs_cfg.sm_sc = 1;
|
||||||
ble_hs_cfg.sm_our_key_dist = 1;
|
ble_hs_cfg.sm_our_key_dist = BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
|
||||||
ble_hs_cfg.sm_their_key_dist = 3;
|
ble_hs_cfg.sm_their_key_dist = BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
|
||||||
|
|
||||||
ble_hs_cfg.store_status_cb = ble_store_util_status_rr; /*TODO: Implement handler for this*/
|
ble_hs_cfg.store_status_cb = ble_store_util_status_rr; /*TODO: Implement handler for this*/
|
||||||
|
|
||||||
// Set the device name.
|
// Set the device name.
|
||||||
rc = ble_svc_gap_device_name_set(deviceName.c_str());
|
rc = ble_svc_gap_device_name_set(deviceName.c_str());
|
||||||
assert(rc == 0);
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "ble_svc_gap_device_name_set() failed; rc=%d", rc);
|
||||||
|
}
|
||||||
|
|
||||||
ble_store_config_init();
|
ble_store_config_init();
|
||||||
|
|
||||||
@ -935,13 +950,13 @@ void NimBLEDevice::deinit(bool clearAll) {
|
|||||||
int ret = nimble_port_stop();
|
int ret = nimble_port_stop();
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
nimble_port_deinit();
|
nimble_port_deinit();
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef CONFIG_NIMBLE_CPP_IDF
|
||||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
# if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
ret = esp_nimble_hci_and_controller_deinit();
|
ret = esp_nimble_hci_and_controller_deinit();
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret);
|
NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret);
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
initialized = false;
|
initialized = false;
|
||||||
m_synced = false;
|
m_synced = false;
|
||||||
@ -1150,6 +1165,43 @@ int NimBLEDevice::startSecurity(uint16_t conn_id) {
|
|||||||
} // startSecurity
|
} // startSecurity
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Inject the provided passkey into the Security Manager
|
||||||
|
* @param [in] peerInfo Connection information for the peer
|
||||||
|
* @param [in] pin The 6-digit pin to inject
|
||||||
|
* @return true if the passkey was injected successfully.
|
||||||
|
*/
|
||||||
|
bool NimBLEDevice::injectPassKey(const NimBLEConnInfo& peerInfo, uint32_t pin) {
|
||||||
|
int rc = 0;
|
||||||
|
struct ble_sm_io pkey = {0,0};
|
||||||
|
|
||||||
|
pkey.action = BLE_SM_IOACT_INPUT;
|
||||||
|
pkey.passkey = pin;
|
||||||
|
|
||||||
|
rc = ble_sm_inject_io(peerInfo.getConnHandle(), &pkey);
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_INPUT; ble_sm_inject_io result: %d", rc);
|
||||||
|
return rc == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Inject the provided numeric comparison response into the Security Manager
|
||||||
|
* @param [in] peerInfo Connection information for the peer
|
||||||
|
* @param [in] accept Whether the user confirmed or declined the comparison
|
||||||
|
*/
|
||||||
|
bool NimBLEDevice::injectConfirmPIN(const NimBLEConnInfo& peerInfo, bool accept) {
|
||||||
|
int rc = 0;
|
||||||
|
struct ble_sm_io pkey = {0,0};
|
||||||
|
|
||||||
|
pkey.action = BLE_SM_IOACT_NUMCMP;
|
||||||
|
pkey.numcmp_accept = accept;
|
||||||
|
|
||||||
|
rc = ble_sm_inject_io(peerInfo.getConnHandle(), &pkey);
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_NUMCMP; ble_sm_inject_io result: %d", rc);
|
||||||
|
return rc == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if the device address is on our ignore list.
|
* @brief Check if the device address is on our ignore list.
|
||||||
* @param [in] address The address to look for.
|
* @param [in] address The address to look for.
|
||||||
@ -1202,10 +1254,22 @@ void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) {
|
|||||||
int rc = ble_gap_event_listener_register(&m_listener, m_customGapHandler, NULL);
|
int rc = ble_gap_event_listener_register(&m_listener, m_customGapHandler, NULL);
|
||||||
if(rc == BLE_HS_EALREADY){
|
if(rc == BLE_HS_EALREADY){
|
||||||
NIMBLE_LOGI(LOG_TAG, "Already listening to GAP events.");
|
NIMBLE_LOGI(LOG_TAG, "Already listening to GAP events.");
|
||||||
|
} else if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "ble_gap_event_listener_register: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
assert(rc == 0);
|
|
||||||
}
|
|
||||||
} // setCustomGapHandler
|
} // setCustomGapHandler
|
||||||
|
|
||||||
#endif // CONFIG_BT_ENABLED
|
#if CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED || __DOXYGEN__
|
||||||
|
/**
|
||||||
|
* @brief Debug assert - weak function.
|
||||||
|
* @param [in] file The file where the assert occurred.
|
||||||
|
* @param [in] line The line number where the assert occurred.
|
||||||
|
*/
|
||||||
|
void nimble_cpp_assert(const char *file, unsigned line) {
|
||||||
|
NIMBLE_LOGC("", "Assertion failed at %s:%u\n", file, line);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif // CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED
|
||||||
|
|
||||||
|
#endif // CONFIG_BT_ENABLED
|
||||||
@ -136,6 +136,8 @@ public:
|
|||||||
static void setSecurityPasskey(uint32_t pin);
|
static void setSecurityPasskey(uint32_t pin);
|
||||||
static uint32_t getSecurityPasskey();
|
static uint32_t getSecurityPasskey();
|
||||||
static int startSecurity(uint16_t conn_id);
|
static int startSecurity(uint16_t conn_id);
|
||||||
|
static bool injectConfirmPIN(const NimBLEConnInfo& peerInfo, bool accept);
|
||||||
|
static bool injectPassKey(const NimBLEConnInfo& peerInfo, uint32_t pin);
|
||||||
static int setMTU(uint16_t mtu);
|
static int setMTU(uint16_t mtu);
|
||||||
static uint16_t getMTU();
|
static uint16_t getMTU();
|
||||||
static bool isIgnored(const NimBLEAddress &address);
|
static bool isIgnored(const NimBLEAddress &address);
|
||||||
@ -172,7 +174,7 @@ public:
|
|||||||
static bool deleteBond(const NimBLEAddress &address);
|
static bool deleteBond(const NimBLEAddress &address);
|
||||||
static int getNumBonds();
|
static int getNumBonds();
|
||||||
static bool isBonded(const NimBLEAddress &address);
|
static bool isBonded(const NimBLEAddress &address);
|
||||||
static void deleteAllBonds();
|
static bool deleteAllBonds();
|
||||||
static NimBLEAddress getBondedAddress(int index);
|
static NimBLEAddress getBondedAddress(int index);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -81,7 +81,7 @@ uint16_t NimBLEEddystoneTLM::getVolt() {
|
|||||||
* @return The temperature value.
|
* @return The temperature value.
|
||||||
*/
|
*/
|
||||||
float NimBLEEddystoneTLM::getTemp() {
|
float NimBLEEddystoneTLM::getTemp() {
|
||||||
return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f;
|
return (int16_t)ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f;
|
||||||
} // getTemp
|
} // getTemp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,7 +203,7 @@ void NimBLEEddystoneTLM::setVolt(uint16_t volt) {
|
|||||||
* @param [in] temp The temperature value.
|
* @param [in] temp The temperature value.
|
||||||
*/
|
*/
|
||||||
void NimBLEEddystoneTLM::setTemp(float temp) {
|
void NimBLEEddystoneTLM::setTemp(float temp) {
|
||||||
m_eddystoneData.temp = (uint16_t)temp;
|
m_eddystoneData.temp = ENDIAN_CHANGE_U16((int16_t)(temp * 256.0f));
|
||||||
} // setTemp
|
} // setTemp
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -341,7 +341,7 @@ int NimBLEExtAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg)
|
|||||||
case BLE_HS_EOS:
|
case BLE_HS_EOS:
|
||||||
case BLE_HS_ECONTROLLER:
|
case BLE_HS_ECONTROLLER:
|
||||||
case BLE_HS_ENOTSYNCED:
|
case BLE_HS_ENOTSYNCED:
|
||||||
NIMBLE_LOGC(LOG_TAG, "host reset, rc = %d", event->adv_complete.reason);
|
NIMBLE_LOGE(LOG_TAG, "host reset, rc = %d", event->adv_complete.reason);
|
||||||
NimBLEDevice::onReset(event->adv_complete.reason);
|
NimBLEDevice::onReset(event->adv_complete.reason);
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
@ -623,9 +623,6 @@ void NimBLEExtAdvertisement::addData(const uint8_t * data, size_t length) {
|
|||||||
/**
|
/**
|
||||||
* @brief Set the appearance.
|
* @brief Set the appearance.
|
||||||
* @param [in] appearance The appearance code value.
|
* @param [in] appearance The appearance code value.
|
||||||
*
|
|
||||||
* See also:
|
|
||||||
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml
|
|
||||||
*/
|
*/
|
||||||
void NimBLEExtAdvertisement::setAppearance(uint16_t appearance) {
|
void NimBLEExtAdvertisement::setAppearance(uint16_t appearance) {
|
||||||
char cdata[2];
|
char cdata[2];
|
||||||
|
|||||||
@ -26,28 +26,34 @@ NimBLEHIDDevice::NimBLEHIDDevice(NimBLEServer* server) {
|
|||||||
/*
|
/*
|
||||||
* Here we create mandatory services described in bluetooth specification
|
* Here we create mandatory services described in bluetooth specification
|
||||||
*/
|
*/
|
||||||
m_deviceInfoService = server->createService(NimBLEUUID((uint16_t) 0x180a));
|
m_deviceInfoService = server->createService(NimBLEUUID((uint16_t)0x180a));
|
||||||
m_hidService = server->createService(NimBLEUUID((uint16_t) 0x1812));
|
m_hidService = server->createService(NimBLEUUID((uint16_t)0x1812));
|
||||||
m_batteryService = server->createService(NimBLEUUID((uint16_t) 0x180f));
|
m_batteryService = server->createService(NimBLEUUID((uint16_t)0x180f));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mandatory characteristic for device info service
|
* Mandatory characteristic for device info service
|
||||||
*/
|
*/
|
||||||
m_pnpCharacteristic = m_deviceInfoService->createCharacteristic((uint16_t) 0x2a50, NIMBLE_PROPERTY::READ);
|
m_pnpCharacteristic = m_deviceInfoService->createCharacteristic((uint16_t)0x2a50, NIMBLE_PROPERTY::READ);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non-mandatory characteristics for device info service
|
||||||
|
* Will be created on demand
|
||||||
|
*/
|
||||||
|
m_manufacturerCharacteristic = nullptr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mandatory characteristics for HID service
|
* Mandatory characteristics for HID service
|
||||||
*/
|
*/
|
||||||
m_hidInfoCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4a, NIMBLE_PROPERTY::READ);
|
m_hidInfoCharacteristic = m_hidService->createCharacteristic((uint16_t)0x2a4a, NIMBLE_PROPERTY::READ);
|
||||||
m_reportMapCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4b, NIMBLE_PROPERTY::READ);
|
m_reportMapCharacteristic = m_hidService->createCharacteristic((uint16_t)0x2a4b, NIMBLE_PROPERTY::READ);
|
||||||
m_hidControlCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4c, NIMBLE_PROPERTY::WRITE_NR);
|
m_hidControlCharacteristic = m_hidService->createCharacteristic((uint16_t)0x2a4c, NIMBLE_PROPERTY::WRITE_NR);
|
||||||
m_protocolModeCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4e, NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::READ);
|
m_protocolModeCharacteristic = m_hidService->createCharacteristic((uint16_t)0x2a4e, NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::READ);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mandatory battery level characteristic with notification and presence descriptor
|
* Mandatory battery level characteristic with notification and presence descriptor
|
||||||
*/
|
*/
|
||||||
m_batteryLevelCharacteristic = m_batteryService->createCharacteristic((uint16_t) 0x2a19, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
|
m_batteryLevelCharacteristic = m_batteryService->createCharacteristic((uint16_t)0x2a19, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
|
||||||
NimBLE2904* batteryLevelDescriptor = (NimBLE2904*)m_batteryLevelCharacteristic->createDescriptor((uint16_t) 0x2904);
|
NimBLE2904 *batteryLevelDescriptor = (NimBLE2904*)m_batteryLevelCharacteristic->createDescriptor((uint16_t)0x2904);
|
||||||
batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8);
|
batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8);
|
||||||
batteryLevelDescriptor->setNamespace(1);
|
batteryLevelDescriptor->setNamespace(1);
|
||||||
batteryLevelDescriptor->setUnit(0x27ad);
|
batteryLevelDescriptor->setUnit(0x27ad);
|
||||||
@ -56,8 +62,8 @@ NimBLEHIDDevice::NimBLEHIDDevice(NimBLEServer* server) {
|
|||||||
* This value is setup here because its default value in most usage cases, its very rare to use boot mode
|
* This value is setup here because its default value in most usage cases, its very rare to use boot mode
|
||||||
* and we want to simplify library using as much as possible
|
* and we want to simplify library using as much as possible
|
||||||
*/
|
*/
|
||||||
const uint8_t pMode[] = { 0x01 };
|
const uint8_t pMode[] = {0x01};
|
||||||
protocolMode()->setValue((uint8_t*) pMode, 1);
|
protocolMode()->setValue((uint8_t*)pMode, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
NimBLEHIDDevice::~NimBLEHIDDevice() {
|
NimBLEHIDDevice::~NimBLEHIDDevice() {
|
||||||
@ -86,7 +92,10 @@ void NimBLEHIDDevice::startServices() {
|
|||||||
* @brief Create a manufacturer characteristic (this characteristic is optional).
|
* @brief Create a manufacturer characteristic (this characteristic is optional).
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEHIDDevice::manufacturer() {
|
NimBLECharacteristic* NimBLEHIDDevice::manufacturer() {
|
||||||
m_manufacturerCharacteristic = m_deviceInfoService->createCharacteristic((uint16_t) 0x2a29, NIMBLE_PROPERTY::READ);
|
if (m_manufacturerCharacteristic == nullptr) {
|
||||||
|
m_manufacturerCharacteristic = m_deviceInfoService->createCharacteristic((uint16_t)0x2a29, NIMBLE_PROPERTY::READ);
|
||||||
|
}
|
||||||
|
|
||||||
return m_manufacturerCharacteristic;
|
return m_manufacturerCharacteristic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +104,7 @@ NimBLECharacteristic* NimBLEHIDDevice::manufacturer() {
|
|||||||
* @param [in] name The manufacturer name of this HID device.
|
* @param [in] name The manufacturer name of this HID device.
|
||||||
*/
|
*/
|
||||||
void NimBLEHIDDevice::manufacturer(std::string name) {
|
void NimBLEHIDDevice::manufacturer(std::string name) {
|
||||||
m_manufacturerCharacteristic->setValue(name);
|
manufacturer()->setValue(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,7 +115,15 @@ void NimBLEHIDDevice::manufacturer(std::string name) {
|
|||||||
* @param [in] version The produce version number.
|
* @param [in] version The produce version number.
|
||||||
*/
|
*/
|
||||||
void NimBLEHIDDevice::pnp(uint8_t sig, uint16_t vid, uint16_t pid, uint16_t version) {
|
void NimBLEHIDDevice::pnp(uint8_t sig, uint16_t vid, uint16_t pid, uint16_t version) {
|
||||||
uint8_t pnp[] = { sig, (uint8_t) (vid >> 8), (uint8_t) vid, (uint8_t) (pid >> 8), (uint8_t) pid, (uint8_t) (version >> 8), (uint8_t) version };
|
uint8_t pnp[] = {
|
||||||
|
sig,
|
||||||
|
((uint8_t*)&vid)[0],
|
||||||
|
((uint8_t*)&vid)[1],
|
||||||
|
((uint8_t*)&pid)[0],
|
||||||
|
((uint8_t*)&pid)[1],
|
||||||
|
((uint8_t*)&version)[0],
|
||||||
|
((uint8_t*)&version)[1]
|
||||||
|
};
|
||||||
m_pnpCharacteristic->setValue(pnp, sizeof(pnp));
|
m_pnpCharacteristic->setValue(pnp, sizeof(pnp));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +133,7 @@ void NimBLEHIDDevice::pnp(uint8_t sig, uint16_t vid, uint16_t pid, uint16_t vers
|
|||||||
* @param [in] flags The HID Class Specification release number to use.
|
* @param [in] flags The HID Class Specification release number to use.
|
||||||
*/
|
*/
|
||||||
void NimBLEHIDDevice::hidInfo(uint8_t country, uint8_t flags) {
|
void NimBLEHIDDevice::hidInfo(uint8_t country, uint8_t flags) {
|
||||||
uint8_t info[] = { 0x11, 0x1, country, flags };
|
uint8_t info[] = {0x11, 0x1, country, flags};
|
||||||
m_hidInfoCharacteristic->setValue(info, sizeof(info));
|
m_hidInfoCharacteristic->setValue(info, sizeof(info));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,11 +143,11 @@ void NimBLEHIDDevice::hidInfo(uint8_t country, uint8_t flags) {
|
|||||||
* @return pointer to new input report characteristic
|
* @return pointer to new input report characteristic
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
||||||
NimBLECharacteristic* inputReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ_ENC);
|
NimBLECharacteristic *inputReportCharacteristic = m_hidService->createCharacteristic((uint16_t)0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ_ENC);
|
||||||
NimBLEDescriptor* inputReportDescriptor = inputReportCharacteristic->createDescriptor((uint16_t) 0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC);
|
NimBLEDescriptor *inputReportDescriptor = inputReportCharacteristic->createDescriptor((uint16_t)0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC);
|
||||||
|
|
||||||
uint8_t desc1_val[] = { reportID, 0x01 };
|
uint8_t desc1_val[] = {reportID, 0x01};
|
||||||
inputReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
inputReportDescriptor->setValue((uint8_t*)desc1_val, 2);
|
||||||
|
|
||||||
return inputReportCharacteristic;
|
return inputReportCharacteristic;
|
||||||
}
|
}
|
||||||
@ -141,11 +158,11 @@ NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
|||||||
* @return Pointer to new output report characteristic
|
* @return Pointer to new output report characteristic
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEHIDDevice::outputReport(uint8_t reportID) {
|
NimBLECharacteristic* NimBLEHIDDevice::outputReport(uint8_t reportID) {
|
||||||
NimBLECharacteristic* outputReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
NimBLECharacteristic *outputReportCharacteristic = m_hidService->createCharacteristic((uint16_t)0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||||
NimBLEDescriptor* outputReportDescriptor = outputReportCharacteristic->createDescriptor((uint16_t) 0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
NimBLEDescriptor *outputReportDescriptor = outputReportCharacteristic->createDescriptor((uint16_t)0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||||
|
|
||||||
uint8_t desc1_val[] = { reportID, 0x02 };
|
uint8_t desc1_val[] = {reportID, 0x02};
|
||||||
outputReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
outputReportDescriptor->setValue((uint8_t*)desc1_val, 2);
|
||||||
|
|
||||||
return outputReportCharacteristic;
|
return outputReportCharacteristic;
|
||||||
}
|
}
|
||||||
@ -156,11 +173,11 @@ NimBLECharacteristic* NimBLEHIDDevice::outputReport(uint8_t reportID) {
|
|||||||
* @return Pointer to new feature report characteristic
|
* @return Pointer to new feature report characteristic
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEHIDDevice::featureReport(uint8_t reportID) {
|
NimBLECharacteristic* NimBLEHIDDevice::featureReport(uint8_t reportID) {
|
||||||
NimBLECharacteristic* featureReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
NimBLECharacteristic *featureReportCharacteristic = m_hidService->createCharacteristic((uint16_t)0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||||
NimBLEDescriptor* featureReportDescriptor = featureReportCharacteristic->createDescriptor((uint16_t) 0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
NimBLEDescriptor *featureReportDescriptor = featureReportCharacteristic->createDescriptor((uint16_t)0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||||
|
|
||||||
uint8_t desc1_val[] = { reportID, 0x03 };
|
uint8_t desc1_val[] = {reportID, 0x03};
|
||||||
featureReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
featureReportDescriptor->setValue((uint8_t*)desc1_val, 2);
|
||||||
|
|
||||||
return featureReportCharacteristic;
|
return featureReportCharacteristic;
|
||||||
}
|
}
|
||||||
@ -169,14 +186,14 @@ NimBLECharacteristic* NimBLEHIDDevice::featureReport(uint8_t reportID) {
|
|||||||
* @brief Creates a keyboard boot input report characteristic
|
* @brief Creates a keyboard boot input report characteristic
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEHIDDevice::bootInput() {
|
NimBLECharacteristic* NimBLEHIDDevice::bootInput() {
|
||||||
return m_hidService->createCharacteristic((uint16_t) 0x2a22, NIMBLE_PROPERTY::NOTIFY);
|
return m_hidService->createCharacteristic((uint16_t)0x2a22, NIMBLE_PROPERTY::NOTIFY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a keyboard boot output report characteristic
|
* @brief Create a keyboard boot output report characteristic
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEHIDDevice::bootOutput() {
|
NimBLECharacteristic* NimBLEHIDDevice::bootOutput() {
|
||||||
return m_hidService->createCharacteristic((uint16_t) 0x2a32, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR);
|
return m_hidService->createCharacteristic((uint16_t)0x2a32, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
#define HID_DIGITAL_PEN 0x03C7
|
#define HID_DIGITAL_PEN 0x03C7
|
||||||
#define HID_BARCODE 0x03C8
|
#define HID_BARCODE 0x03C8
|
||||||
|
|
||||||
|
#define PNPVersionField(MajorVersion, MinorVersion, PatchVersion) ((MajorVersion << 16) & 0xFF00) | ((MinorVersion << 8) & 0x00F0) | (PatchVersion & 0x000F)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A model of a %BLE Human Interface Device.
|
* @brief A model of a %BLE Human Interface Device.
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#if defined(CONFIG_NIMBLE_CPP_IDF) // using esp-idf
|
#if defined(CONFIG_NIMBLE_CPP_IDF) // using esp-idf
|
||||||
# include "esp_log.h"
|
# include "esp_log.h"
|
||||||
|
# include "console/console.h"
|
||||||
# ifndef CONFIG_NIMBLE_CPP_LOG_LEVEL
|
# ifndef CONFIG_NIMBLE_CPP_LOG_LEVEL
|
||||||
# define CONFIG_NIMBLE_CPP_LOG_LEVEL 0
|
# define CONFIG_NIMBLE_CPP_LOG_LEVEL 0
|
||||||
# endif
|
# endif
|
||||||
@ -35,22 +36,6 @@
|
|||||||
# define NIMBLE_LOGE(tag, format, ...) \
|
# define NIMBLE_LOGE(tag, format, ...) \
|
||||||
NIMBLE_CPP_LOG_PRINT(ESP_LOG_ERROR, tag, format, ##__VA_ARGS__)
|
NIMBLE_CPP_LOG_PRINT(ESP_LOG_ERROR, tag, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
# define NIMBLE_LOGC(tag, format, ...) \
|
|
||||||
NIMBLE_CPP_LOG_PRINT(ESP_LOG_ERROR, tag, format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
// These defines pollute the global namespace and conflict with Tasmota and basically always turn on `seriallog 3`
|
|
||||||
#ifdef LOG_LEVEL_DEBUG
|
|
||||||
#undef LOG_LEVEL_DEBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LOG_LEVEL_INFO
|
|
||||||
#undef LOG_LEVEL_INFO
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LOG_LEVEL_ERROR
|
|
||||||
#undef LOG_LEVEL_ERROR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else // using Arduino
|
#else // using Arduino
|
||||||
# include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
# include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||||
# include "nimble/console/console.h"
|
# include "nimble/console/console.h"
|
||||||
@ -82,12 +67,13 @@
|
|||||||
|
|
||||||
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 1
|
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 1
|
||||||
# define NIMBLE_LOGE( tag, format, ... ) console_printf("E %s: " format "\n", tag, ##__VA_ARGS__)
|
# define NIMBLE_LOGE( tag, format, ... ) console_printf("E %s: " format "\n", tag, ##__VA_ARGS__)
|
||||||
# define NIMBLE_LOGC( tag, format, ... ) console_printf("CRIT %s: " format "\n", tag, ##__VA_ARGS__)
|
|
||||||
# else
|
# else
|
||||||
# define NIMBLE_LOGE( tag, format, ... ) (void)tag
|
# define NIMBLE_LOGE( tag, format, ... ) (void)tag
|
||||||
# define NIMBLE_LOGC( tag, format, ... ) (void)tag
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif /* CONFIG_NIMBLE_CPP_IDF */
|
#endif /* CONFIG_NIMBLE_CPP_IDF */
|
||||||
|
|
||||||
|
#define NIMBLE_LOGC( tag, format, ... ) console_printf("CRIT %s: " format "\n", tag, ##__VA_ARGS__)
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* MAIN_NIMBLELOG_H_ */
|
#endif /* MAIN_NIMBLELOG_H_ */
|
||||||
|
|||||||
@ -359,7 +359,7 @@ bool NimBLEScan::start(uint32_t duration, bool is_continue) {
|
|||||||
case BLE_HS_EOS:
|
case BLE_HS_EOS:
|
||||||
case BLE_HS_ECONTROLLER:
|
case BLE_HS_ECONTROLLER:
|
||||||
case BLE_HS_ENOTSYNCED:
|
case BLE_HS_ENOTSYNCED:
|
||||||
NIMBLE_LOGC(LOG_TAG, "Unable to scan - Host Reset");
|
NIMBLE_LOGE(LOG_TAG, "Unable to scan - Host Reset");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -459,7 +459,7 @@ void NimBLEScan::onHostSync() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start scanning and block until scanning has been completed.
|
* @brief Start scanning and block until scanning has been completed.
|
||||||
* @param [in] duration The duration in seconds for which to scan.
|
* @param [in] duration The duration in milliseconds for which to scan.
|
||||||
* @param [in] is_continue Set to true to save previous scan results, false to clear them.
|
* @param [in] is_continue Set to true to save previous scan results, false to clear them.
|
||||||
* @return The scan results.
|
* @return The scan results.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -27,6 +27,11 @@
|
|||||||
#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h"
|
#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#define NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB 0
|
||||||
|
#define NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB 1
|
||||||
|
|
||||||
static const char* LOG_TAG = "NimBLEServer";
|
static const char* LOG_TAG = "NimBLEServer";
|
||||||
static NimBLEServerCallbacks defaultCallbacks;
|
static NimBLEServerCallbacks defaultCallbacks;
|
||||||
|
|
||||||
@ -47,6 +52,7 @@ NimBLEServer::NimBLEServer() {
|
|||||||
#endif
|
#endif
|
||||||
m_svcChanged = false;
|
m_svcChanged = false;
|
||||||
m_deleteCallbacks = true;
|
m_deleteCallbacks = true;
|
||||||
|
m_getPeerNameOnConnect = false;
|
||||||
} // NimBLEServer
|
} // NimBLEServer
|
||||||
|
|
||||||
|
|
||||||
@ -186,9 +192,8 @@ void NimBLEServer::start() {
|
|||||||
|
|
||||||
int rc = ble_gatts_start();
|
int rc = ble_gatts_start();
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "ble_gatts_start; rc=%d, %s", rc,
|
NIMBLE_LOGE(LOG_TAG, "ble_gatts_start; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
NimBLEUtils::returnCodeToString(rc));
|
return;
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 4
|
#if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 4
|
||||||
@ -215,7 +220,9 @@ void NimBLEServer::start() {
|
|||||||
if(svc->m_removed == 0) {
|
if(svc->m_removed == 0) {
|
||||||
rc = ble_gatts_find_svc(&svc->getUUID().getNative()->u, &svc->m_handle);
|
rc = ble_gatts_find_svc(&svc->getUUID().getNative()->u, &svc->m_handle);
|
||||||
if(rc != 0) {
|
if(rc != 0) {
|
||||||
abort();
|
NIMBLE_LOGW(LOG_TAG, "GATT Server started without service: %s, Service %s",
|
||||||
|
svc->getUUID().toString().c_str(), svc->isStarted() ? "missing" : "not started");
|
||||||
|
continue; // Skip this service as it was not started
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +259,15 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
|
|||||||
return rc;
|
return rc;
|
||||||
} // disconnect
|
} // disconnect
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disconnect the specified client with optional reason.
|
||||||
|
* @param [in] connInfo Connection of the client to disconnect.
|
||||||
|
* @param [in] reason code for disconnecting.
|
||||||
|
* @return NimBLE host return code.
|
||||||
|
*/
|
||||||
|
int NimBLEServer::disconnect(const NimBLEConnInfo &connInfo, uint8_t reason) {
|
||||||
|
return disconnect(connInfo.getConnHandle(), reason);
|
||||||
|
} // disconnect
|
||||||
|
|
||||||
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||||
/**
|
/**
|
||||||
@ -263,6 +279,15 @@ void NimBLEServer::advertiseOnDisconnect(bool aod) {
|
|||||||
} // advertiseOnDisconnect
|
} // advertiseOnDisconnect
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the server to automatically read the name from the connected peer before
|
||||||
|
* the onConnect callback is called and enables the override callback with name parameter.
|
||||||
|
* @param [in] enable Enable reading the connected peer name upon connection.
|
||||||
|
*/
|
||||||
|
void NimBLEServer::getPeerNameOnConnect(bool enable) {
|
||||||
|
m_getPeerNameOnConnect = enable;
|
||||||
|
} // getPeerNameOnConnect
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return the number of connected clients.
|
* @brief Return the number of connected clients.
|
||||||
* @return The number of connected clients.
|
* @return The number of connected clients.
|
||||||
@ -328,6 +353,113 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
|||||||
return peerInfo;
|
return peerInfo;
|
||||||
} // getPeerIDInfo
|
} // getPeerIDInfo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback that is called after reading from the peer name characteristic.
|
||||||
|
* @details This will check the task pointer in the task data struct to determine
|
||||||
|
* the action to take once the name has been read. If there is a task waiting then
|
||||||
|
* it will be woken, if not, the the RC value is checked to determine which callback
|
||||||
|
* should be called.
|
||||||
|
*/
|
||||||
|
int NimBLEServer::peerNameCB(uint16_t conn_handle,
|
||||||
|
const struct ble_gatt_error *error,
|
||||||
|
struct ble_gatt_attr *attr,
|
||||||
|
void *arg) {
|
||||||
|
ble_task_data_t *pTaskData = (ble_task_data_t*)arg;
|
||||||
|
std::string *name = (std::string*)pTaskData->buf;
|
||||||
|
int rc = error->status;
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
if (attr) {
|
||||||
|
name->append(OS_MBUF_DATA(attr->om, char*), OS_MBUF_PKTLEN(attr->om));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == BLE_HS_EDONE) {
|
||||||
|
// No ask means this was read for a callback.
|
||||||
|
if (pTaskData->task == nullptr) {
|
||||||
|
NimBLEServer* pServer = (NimBLEServer*)pTaskData->pATT;
|
||||||
|
NimBLEConnInfo peerInfo{};
|
||||||
|
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||||
|
|
||||||
|
// Use the rc value as a flag to indicate which callback should be called.
|
||||||
|
if (pTaskData->rc == NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB) {
|
||||||
|
pServer->m_pServerCallbacks->onConnect(pServer, peerInfo, *name);
|
||||||
|
} else if (pTaskData->rc == NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB) {
|
||||||
|
pServer->m_pServerCallbacks->onAuthenticationComplete(peerInfo, *name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "NimBLEServerPeerNameCB rc=%d; %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTaskData->task != nullptr) {
|
||||||
|
pTaskData->rc = rc;
|
||||||
|
xTaskNotifyGive(pTaskData->task);
|
||||||
|
} else {
|
||||||
|
// If the read was triggered for callback use then these were allocated.
|
||||||
|
delete name;
|
||||||
|
delete pTaskData;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Internal method that sends the read command.
|
||||||
|
*/
|
||||||
|
std::string NimBLEServer::getPeerNameInternal(uint16_t conn_handle, TaskHandle_t task, int cb_type) {
|
||||||
|
std::string *buf = new std::string{};
|
||||||
|
ble_task_data_t *taskData = new ble_task_data_t{this, task, cb_type, buf};
|
||||||
|
ble_uuid16_t uuid {{BLE_UUID_TYPE_16}, BLE_SVC_GAP_CHR_UUID16_DEVICE_NAME};
|
||||||
|
int rc = ble_gattc_read_by_uuid(conn_handle,
|
||||||
|
1,
|
||||||
|
0xffff,
|
||||||
|
((ble_uuid_t*)&uuid),
|
||||||
|
NimBLEServer::peerNameCB,
|
||||||
|
taskData);
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "ble_gattc_read_by_uuid rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
NimBLEConnInfo peerInfo{};
|
||||||
|
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||||
|
if (cb_type == NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB) {
|
||||||
|
m_pServerCallbacks->onConnect(this, peerInfo, *buf);
|
||||||
|
} else if (cb_type == NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB) {
|
||||||
|
m_pServerCallbacks->onAuthenticationComplete(peerInfo, *buf);
|
||||||
|
}
|
||||||
|
delete buf;
|
||||||
|
delete taskData;
|
||||||
|
} else if (task != nullptr) {
|
||||||
|
#ifdef ulTaskNotifyValueClear
|
||||||
|
// Clear the task notification value to ensure we block
|
||||||
|
ulTaskNotifyValueClear(task, ULONG_MAX);
|
||||||
|
#endif
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
rc = taskData->rc;
|
||||||
|
std::string name{*(std::string*)taskData->buf};
|
||||||
|
delete buf;
|
||||||
|
delete taskData;
|
||||||
|
|
||||||
|
if (rc != 0 && rc != BLE_HS_EDONE) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "getPeerName rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
// TaskData and name buffer will be deleted in the callback.
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the name of the connected peer.
|
||||||
|
* @param connInfo A reference to a NimBLEConnInfo instance to read the name from.
|
||||||
|
* @returns A string containing the name.
|
||||||
|
* @note This is a blocking call and should NOT be called from any callbacks!
|
||||||
|
*/
|
||||||
|
std::string NimBLEServer::getPeerName(const NimBLEConnInfo& connInfo) {
|
||||||
|
std::string name = getPeerNameInternal(connInfo.getConnHandle(), xTaskGetCurrentTaskHandle());
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handle a GATT Server Event.
|
* @brief Handle a GATT Server Event.
|
||||||
@ -354,16 +486,22 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
NimBLEDevice::startAdvertising();
|
NimBLEDevice::startAdvertising();
|
||||||
#endif
|
#endif
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pServer->m_connectedPeersVec.push_back(event->connect.conn_handle);
|
|
||||||
|
|
||||||
rc = ble_gap_conn_find(event->connect.conn_handle, &peerInfo.m_desc);
|
rc = ble_gap_conn_find(event->connect.conn_handle, &peerInfo.m_desc);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pServer->m_pServerCallbacks->onConnect(pServer, peerInfo);
|
pServer->m_connectedPeersVec.push_back(event->connect.conn_handle);
|
||||||
|
|
||||||
|
if (pServer->m_getPeerNameOnConnect) {
|
||||||
|
pServer->getPeerNameInternal(event->connect.conn_handle,
|
||||||
|
nullptr,
|
||||||
|
NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB);
|
||||||
|
} else {
|
||||||
|
pServer->m_pServerCallbacks->onConnect(pServer, peerInfo);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -378,7 +516,7 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
case BLE_HS_EOS:
|
case BLE_HS_EOS:
|
||||||
case BLE_HS_ECONTROLLER:
|
case BLE_HS_ECONTROLLER:
|
||||||
case BLE_HS_ENOTSYNCED:
|
case BLE_HS_ENOTSYNCED:
|
||||||
NIMBLE_LOGC(LOG_TAG, "Disconnect - host reset, rc=%d", event->disconnect.reason);
|
NIMBLE_LOGE(LOG_TAG, "Disconnect - host reset, rc=%d", event->disconnect.reason);
|
||||||
NimBLEDevice::onReset(event->disconnect.reason);
|
NimBLEDevice::onReset(event->disconnect.reason);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -514,10 +652,26 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
return BLE_ATT_ERR_INVALID_HANDLE;
|
return BLE_ATT_ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
pServer->m_pServerCallbacks->onAuthenticationComplete(peerInfo);
|
if (pServer->m_getPeerNameOnConnect) {
|
||||||
|
pServer->getPeerNameInternal(event->enc_change.conn_handle,
|
||||||
|
nullptr,
|
||||||
|
NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB);
|
||||||
|
} else {
|
||||||
|
pServer->m_pServerCallbacks->onAuthenticationComplete(peerInfo);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} // BLE_GAP_EVENT_ENC_CHANGE
|
} // BLE_GAP_EVENT_ENC_CHANGE
|
||||||
|
|
||||||
|
case BLE_GAP_EVENT_IDENTITY_RESOLVED: {
|
||||||
|
rc = ble_gap_conn_find(event->identity_resolved.conn_handle, &peerInfo.m_desc);
|
||||||
|
if(rc != 0) {
|
||||||
|
return BLE_ATT_ERR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pServer->m_pServerCallbacks->onIdentity(peerInfo);
|
||||||
|
return 0;
|
||||||
|
} // BLE_GAP_EVENT_IDENTITY_RESOLVED
|
||||||
|
|
||||||
case BLE_GAP_EVENT_PASSKEY_ACTION: {
|
case BLE_GAP_EVENT_PASSKEY_ACTION: {
|
||||||
struct ble_sm_io pkey = {0,0};
|
struct ble_sm_io pkey = {0,0};
|
||||||
|
|
||||||
@ -528,19 +682,20 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
// if the (static)passkey is the default, check the callback for custom value
|
// if the (static)passkey is the default, check the callback for custom value
|
||||||
// both values default to the same.
|
// both values default to the same.
|
||||||
if(pkey.passkey == 123456) {
|
if(pkey.passkey == 123456) {
|
||||||
pkey.passkey = pServer->m_pServerCallbacks->onPassKeyRequest();
|
pkey.passkey = pServer->m_pServerCallbacks->onPassKeyDisplay();
|
||||||
}
|
}
|
||||||
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
||||||
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_DISP; ble_sm_inject_io result: %d", rc);
|
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_DISP; ble_sm_inject_io result: %d", rc);
|
||||||
|
|
||||||
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
|
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %" PRIu32, event->passkey.params.numcmp);
|
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %" PRIu32, event->passkey.params.numcmp);
|
||||||
pkey.action = event->passkey.params.action;
|
|
||||||
pkey.numcmp_accept = pServer->m_pServerCallbacks->onConfirmPIN(event->passkey.params.numcmp);
|
|
||||||
|
|
||||||
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
rc = ble_gap_conn_find(event->passkey.conn_handle, &peerInfo.m_desc);
|
||||||
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_NUMCMP; ble_sm_inject_io result: %d", rc);
|
if(rc != 0) {
|
||||||
|
return BLE_ATT_ERR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pServer->m_pServerCallbacks->onConfirmPIN(peerInfo, event->passkey.params.numcmp);
|
||||||
//TODO: Handle out of band pairing
|
//TODO: Handle out of band pairing
|
||||||
} else if (event->passkey.params.action == BLE_SM_IOACT_OOB) {
|
} else if (event->passkey.params.action == BLE_SM_IOACT_OOB) {
|
||||||
static uint8_t tem_oob[16] = {0};
|
static uint8_t tem_oob[16] = {0};
|
||||||
@ -551,14 +706,6 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
||||||
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_OOB; ble_sm_inject_io result: %d", rc);
|
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_OOB; ble_sm_inject_io result: %d", rc);
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
} else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Enter the passkey");
|
|
||||||
pkey.action = event->passkey.params.action;
|
|
||||||
pkey.passkey = pServer->m_pServerCallbacks->onPassKeyRequest();
|
|
||||||
|
|
||||||
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_INPUT; ble_sm_inject_io result: %d", rc);
|
|
||||||
|
|
||||||
} else if (event->passkey.params.action == BLE_SM_IOACT_NONE) {
|
} else if (event->passkey.params.action == BLE_SM_IOACT_NONE) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "No passkey action required");
|
NIMBLE_LOGD(LOG_TAG, "No passkey action required");
|
||||||
}
|
}
|
||||||
@ -842,6 +989,10 @@ void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& con
|
|||||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
||||||
} // onConnect
|
} // onConnect
|
||||||
|
|
||||||
|
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, std::string& name) {
|
||||||
|
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
||||||
|
} // onConnect
|
||||||
|
|
||||||
void NimBLEServerCallbacks::onDisconnect(NimBLEServer* pServer,
|
void NimBLEServerCallbacks::onDisconnect(NimBLEServer* pServer,
|
||||||
NimBLEConnInfo& connInfo, int reason) {
|
NimBLEConnInfo& connInfo, int reason) {
|
||||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onDisconnect(): Default");
|
NIMBLE_LOGD("NimBLEServerCallbacks", "onDisconnect(): Default");
|
||||||
@ -851,18 +1002,26 @@ void NimBLEServerCallbacks::onMTUChange(uint16_t MTU, NimBLEConnInfo& connInfo)
|
|||||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onMTUChange(): Default");
|
NIMBLE_LOGD("NimBLEServerCallbacks", "onMTUChange(): Default");
|
||||||
} // onMTUChange
|
} // onMTUChange
|
||||||
|
|
||||||
uint32_t NimBLEServerCallbacks::onPassKeyRequest(){
|
uint32_t NimBLEServerCallbacks::onPassKeyDisplay(){
|
||||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onPassKeyRequest: default: 123456");
|
NIMBLE_LOGD("NimBLEServerCallbacks", "onPassKeyDisplay: default: 123456");
|
||||||
return 123456;
|
return 123456;
|
||||||
} //onPassKeyRequest
|
} //onPassKeyDisplay
|
||||||
|
|
||||||
void NimBLEServerCallbacks::onAuthenticationComplete(NimBLEConnInfo& connInfo){
|
void NimBLEServerCallbacks::onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pin){
|
||||||
|
NIMBLE_LOGD("NimBLEServerCallbacks", "onConfirmPIN: default: true");
|
||||||
|
NimBLEDevice::injectConfirmPIN(connInfo, true);
|
||||||
|
} // onConfirmPIN
|
||||||
|
|
||||||
|
void NimBLEServerCallbacks::onIdentity(const NimBLEConnInfo& connInfo){
|
||||||
|
NIMBLE_LOGD("NimBLEServerCallbacks", "onIdentity: default");
|
||||||
|
} // onIdentity
|
||||||
|
|
||||||
|
void NimBLEServerCallbacks::onAuthenticationComplete(const NimBLEConnInfo& connInfo){
|
||||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onAuthenticationComplete: default");
|
NIMBLE_LOGD("NimBLEServerCallbacks", "onAuthenticationComplete: default");
|
||||||
} // onAuthenticationComplete
|
} // onAuthenticationComplete
|
||||||
|
|
||||||
bool NimBLEServerCallbacks::onConfirmPIN(uint32_t pin){
|
void NimBLEServerCallbacks::onAuthenticationComplete(const NimBLEConnInfo& connInfo, const std::string& name){
|
||||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onConfirmPIN: default: true");
|
NIMBLE_LOGD("NimBLEServerCallbacks", "onAuthenticationComplete: default");
|
||||||
return true;
|
} // onAuthenticationComplete
|
||||||
} // onConfirmPIN
|
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
|
||||||
|
|||||||
@ -69,6 +69,8 @@ public:
|
|||||||
NimBLEService* getServiceByHandle(uint16_t handle);
|
NimBLEService* getServiceByHandle(uint16_t handle);
|
||||||
int disconnect(uint16_t connID,
|
int disconnect(uint16_t connID,
|
||||||
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||||
|
int disconnect(const NimBLEConnInfo &connInfo,
|
||||||
|
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||||
void updateConnParams(uint16_t conn_handle,
|
void updateConnParams(uint16_t conn_handle,
|
||||||
uint16_t minInterval, uint16_t maxInterval,
|
uint16_t minInterval, uint16_t maxInterval,
|
||||||
uint16_t latency, uint16_t timeout);
|
uint16_t latency, uint16_t timeout);
|
||||||
@ -78,6 +80,8 @@ public:
|
|||||||
NimBLEConnInfo getPeerInfo(size_t index);
|
NimBLEConnInfo getPeerInfo(size_t index);
|
||||||
NimBLEConnInfo getPeerInfo(const NimBLEAddress& address);
|
NimBLEConnInfo getPeerInfo(const NimBLEAddress& address);
|
||||||
NimBLEConnInfo getPeerIDInfo(uint16_t id);
|
NimBLEConnInfo getPeerIDInfo(uint16_t id);
|
||||||
|
std::string getPeerName(const NimBLEConnInfo& connInfo);
|
||||||
|
void getPeerNameOnConnect(bool enable);
|
||||||
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||||
void advertiseOnDisconnect(bool);
|
void advertiseOnDisconnect(bool);
|
||||||
#endif
|
#endif
|
||||||
@ -98,6 +102,7 @@ private:
|
|||||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
bool m_advertiseOnDisconnect;
|
bool m_advertiseOnDisconnect;
|
||||||
#endif
|
#endif
|
||||||
|
bool m_getPeerNameOnConnect;
|
||||||
bool m_svcChanged;
|
bool m_svcChanged;
|
||||||
NimBLEServerCallbacks* m_pServerCallbacks;
|
NimBLEServerCallbacks* m_pServerCallbacks;
|
||||||
bool m_deleteCallbacks;
|
bool m_deleteCallbacks;
|
||||||
@ -110,10 +115,14 @@ private:
|
|||||||
std::vector<NimBLECharacteristic*> m_notifyChrVec;
|
std::vector<NimBLECharacteristic*> m_notifyChrVec;
|
||||||
|
|
||||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||||
|
static int peerNameCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||||
|
struct ble_gatt_attr *attr, void *arg);
|
||||||
|
std::string getPeerNameInternal(uint16_t conn_handle, TaskHandle_t task, int cb_type = -1);
|
||||||
void serviceChanged();
|
void serviceChanged();
|
||||||
void resetGATT();
|
void resetGATT();
|
||||||
bool setIndicateWait(uint16_t conn_handle);
|
bool setIndicateWait(uint16_t conn_handle);
|
||||||
void clearIndicateWait(uint16_t conn_handle);
|
void clearIndicateWait(uint16_t conn_handle);
|
||||||
|
|
||||||
}; // NimBLEServer
|
}; // NimBLEServer
|
||||||
|
|
||||||
|
|
||||||
@ -128,11 +137,21 @@ public:
|
|||||||
* @brief Handle a client connection.
|
* @brief Handle a client connection.
|
||||||
* This is called when a client connects.
|
* This is called when a client connects.
|
||||||
* @param [in] pServer A pointer to the %BLE server that received the client connection.
|
* @param [in] pServer A pointer to the %BLE server that received the client connection.
|
||||||
* @param [in] connInfo A reference to a NimBLEConnInfo instance with information
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance with information.
|
||||||
* about the peer connection parameters.
|
* about the peer connection parameters.
|
||||||
*/
|
*/
|
||||||
virtual void onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo);
|
virtual void onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle a client connection.
|
||||||
|
* This is called when a client connects.
|
||||||
|
* @param [in] pServer A pointer to the %BLE server that received the client connection.
|
||||||
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance with information.
|
||||||
|
* @param [in] name The name of the connected peer device.
|
||||||
|
* about the peer connection parameters.
|
||||||
|
*/
|
||||||
|
virtual void onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, std::string& name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handle a client disconnection.
|
* @brief Handle a client disconnection.
|
||||||
* This is called when a client discconnects.
|
* This is called when a client discconnects.
|
||||||
@ -152,24 +171,39 @@ public:
|
|||||||
virtual void onMTUChange(uint16_t MTU, NimBLEConnInfo& connInfo);
|
virtual void onMTUChange(uint16_t MTU, NimBLEConnInfo& connInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when a client requests a passkey for pairing.
|
* @brief Called when a client requests a passkey for pairing (display).
|
||||||
* @return The passkey to be sent to the client.
|
* @return The passkey to be sent to the client.
|
||||||
*/
|
*/
|
||||||
virtual uint32_t onPassKeyRequest();
|
virtual uint32_t onPassKeyDisplay();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when using numeric comparision for pairing.
|
||||||
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance with information
|
||||||
|
* Should be passed back to NimBLEDevice::injectConfirmPIN
|
||||||
|
* @param [in] pin The pin to compare with the client.
|
||||||
|
*/
|
||||||
|
virtual void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when the pairing procedure is complete.
|
* @brief Called when the pairing procedure is complete.
|
||||||
* @param [in] connInfo A reference to a NimBLEConnInfo instance with information
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance with information
|
||||||
* about the peer connection parameters.
|
* about the peer connection parameters.
|
||||||
*/
|
*/
|
||||||
virtual void onAuthenticationComplete(NimBLEConnInfo& connInfo);
|
virtual void onAuthenticationComplete(const NimBLEConnInfo& connInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when using numeric comparision for pairing.
|
* @brief Called when the pairing procedure is complete.
|
||||||
* @param [in] pin The pin to compare with the client.
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance with information
|
||||||
* @return True to accept the pin.
|
* @param [in] name The name of the connected peer device.
|
||||||
|
* about the peer connection parameters.
|
||||||
*/
|
*/
|
||||||
virtual bool onConfirmPIN(uint32_t pin);
|
virtual void onAuthenticationComplete(const NimBLEConnInfo& connInfo, const std::string& name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when the peer identity address is resolved.
|
||||||
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance with information
|
||||||
|
*/
|
||||||
|
virtual void onIdentity(const NimBLEConnInfo& connInfo);
|
||||||
}; // NimBLEServerCallbacks
|
}; // NimBLEServerCallbacks
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
|
||||||
|
|||||||
@ -126,7 +126,7 @@ bool NimBLEService::start() {
|
|||||||
// Nimble requires an array of services to be sent to the api
|
// Nimble requires an array of services to be sent to the api
|
||||||
// Since we are adding 1 at a time we create an array of 2 and set the type
|
// Since we are adding 1 at a time we create an array of 2 and set the type
|
||||||
// of the second service to 0 to indicate the end of the array.
|
// of the second service to 0 to indicate the end of the array.
|
||||||
ble_gatt_svc_def* svc = new ble_gatt_svc_def[2];
|
ble_gatt_svc_def* svc = new ble_gatt_svc_def[2]{};
|
||||||
ble_gatt_chr_def* pChr_a = nullptr;
|
ble_gatt_chr_def* pChr_a = nullptr;
|
||||||
ble_gatt_dsc_def* pDsc_a = nullptr;
|
ble_gatt_dsc_def* pDsc_a = nullptr;
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ bool NimBLEService::start() {
|
|||||||
pChr_a[i].descriptors = NULL;
|
pChr_a[i].descriptors = NULL;
|
||||||
} else {
|
} else {
|
||||||
// Must have last descriptor uuid = 0 so we have to create 1 extra
|
// Must have last descriptor uuid = 0 so we have to create 1 extra
|
||||||
pDsc_a = new ble_gatt_dsc_def[numDscs+1];
|
pDsc_a = new ble_gatt_dsc_def[numDscs+1]{};
|
||||||
int d = 0;
|
int d = 0;
|
||||||
for(auto dsc_it = (*chr_it)->m_dscVec.begin(); dsc_it != (*chr_it)->m_dscVec.end(); ++dsc_it ) {
|
for(auto dsc_it = (*chr_it)->m_dscVec.begin(); dsc_it != (*chr_it)->m_dscVec.end(); ++dsc_it ) {
|
||||||
if((*dsc_it)->m_removed > 0) {
|
if((*dsc_it)->m_removed > 0) {
|
||||||
@ -434,4 +434,14 @@ NimBLEServer* NimBLEService::getServer() {
|
|||||||
return NimBLEDevice::getServer();
|
return NimBLEDevice::getServer();
|
||||||
}// getServer
|
}// getServer
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the service has been started.
|
||||||
|
* @return True if the service has been started.
|
||||||
|
*/
|
||||||
|
bool NimBLEService::isStarted() {
|
||||||
|
return m_pSvcDef != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
|
||||||
|
|||||||
@ -44,7 +44,7 @@ public:
|
|||||||
uint16_t getHandle();
|
uint16_t getHandle();
|
||||||
std::string toString();
|
std::string toString();
|
||||||
void dump();
|
void dump();
|
||||||
|
bool isStarted();
|
||||||
bool start();
|
bool start();
|
||||||
|
|
||||||
NimBLECharacteristic* createCharacteristic(const char* uuid,
|
NimBLECharacteristic* createCharacteristic(const char* uuid,
|
||||||
|
|||||||
@ -16,45 +16,6 @@
|
|||||||
|
|
||||||
static const char* LOG_TAG = "NimBLEUtils";
|
static const char* LOG_TAG = "NimBLEUtils";
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A function for checking validity of connection parameters.
|
|
||||||
* @param [in] params A pointer to the structure containing the parameters to check.
|
|
||||||
* @return valid == 0 or error code.
|
|
||||||
*/
|
|
||||||
int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) {
|
|
||||||
/* Check connection interval min */
|
|
||||||
if ((params->itvl_min < BLE_HCI_CONN_ITVL_MIN) ||
|
|
||||||
(params->itvl_min > BLE_HCI_CONN_ITVL_MAX)) {
|
|
||||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
|
||||||
}
|
|
||||||
/* Check connection interval max */
|
|
||||||
if ((params->itvl_max < BLE_HCI_CONN_ITVL_MIN) ||
|
|
||||||
(params->itvl_max > BLE_HCI_CONN_ITVL_MAX) ||
|
|
||||||
(params->itvl_max < params->itvl_min)) {
|
|
||||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check connection latency */
|
|
||||||
if (params->latency > BLE_HCI_CONN_LATENCY_MAX) {
|
|
||||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check supervision timeout */
|
|
||||||
if ((params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) ||
|
|
||||||
(params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) {
|
|
||||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check connection event length */
|
|
||||||
if (params->min_ce_len > params->max_ce_len) {
|
|
||||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Converts a return code from the NimBLE stack to a text string.
|
* @brief Converts a return code from the NimBLE stack to a text string.
|
||||||
* @param [in] rc The return code to convert.
|
* @param [in] rc The return code to convert.
|
||||||
|
|||||||
@ -43,7 +43,6 @@ public:
|
|||||||
static char* buildHexData(uint8_t* target, const uint8_t* source, uint8_t length);
|
static char* buildHexData(uint8_t* target, const uint8_t* source, uint8_t length);
|
||||||
static const char* advTypeToString(uint8_t advType);
|
static const char* advTypeToString(uint8_t advType);
|
||||||
static const char* returnCodeToString(int rc);
|
static const char* returnCodeToString(int rc);
|
||||||
static int checkConnParams(ble_gap_conn_params* params);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -32,6 +32,18 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED && !defined NDEBUG
|
||||||
|
void nimble_cpp_assert(const char *file, unsigned line) __attribute((weak, noreturn));
|
||||||
|
# define NIMBLE_ATT_VAL_FILE (__builtin_strrchr(__FILE__, '/') ? \
|
||||||
|
__builtin_strrchr (__FILE__, '/') + 1 : __FILE__)
|
||||||
|
# define NIMBLE_CPP_DEBUG_ASSERT(cond) \
|
||||||
|
if (!(cond)) { \
|
||||||
|
nimble_cpp_assert(NIMBLE_ATT_VAL_FILE, __LINE__); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define NIMBLE_CPP_DEBUG_ASSERT(cond) (void(0))
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
||||||
#ifdef _DOXYGEN_
|
#ifdef _DOXYGEN_
|
||||||
|
|||||||
@ -1501,6 +1501,7 @@ set_button_text|lv.obj, string||[lv_list_set_button_text](https://docs.lvgl.io/9
|
|||||||
|
|
||||||
Method|Arguments|Return type|LVGL equivalent
|
Method|Arguments|Return type|LVGL equivalent
|
||||||
:---|:---|:---|:---
|
:---|:---|:---|:---
|
||||||
|
get_anim||lv.anim|[lv_animimg_get_anim](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_get_anim)
|
||||||
get_duration||int|[lv_animimg_get_duration](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_get_duration)
|
get_duration||int|[lv_animimg_get_duration](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_get_duration)
|
||||||
get_repeat_count||int|[lv_animimg_get_repeat_count](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_get_repeat_count)
|
get_repeat_count||int|[lv_animimg_get_repeat_count](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_get_repeat_count)
|
||||||
get_src_count||int|[lv_animimg_get_src_count](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_get_src_count)
|
get_src_count||int|[lv_animimg_get_src_count](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_get_src_count)
|
||||||
|
|||||||
@ -818,6 +818,7 @@ const be_ntv_func_def_t lv_timer_func[] = {
|
|||||||
/* `lv_animimg` methods */
|
/* `lv_animimg` methods */
|
||||||
#ifdef BE_LV_WIDGET_ANIMIMG
|
#ifdef BE_LV_WIDGET_ANIMIMG
|
||||||
const be_ntv_func_def_t lv_animimg_func[] = {
|
const be_ntv_func_def_t lv_animimg_func[] = {
|
||||||
|
{ "get_anim", { (const void*) &lv_animimg_get_anim, "lv.anim", "(lv.obj)" } },
|
||||||
{ "get_duration", { (const void*) &lv_animimg_get_duration, "i", "(lv.obj)" } },
|
{ "get_duration", { (const void*) &lv_animimg_get_duration, "i", "(lv.obj)" } },
|
||||||
{ "get_repeat_count", { (const void*) &lv_animimg_get_repeat_count, "i", "(lv.obj)" } },
|
{ "get_repeat_count", { (const void*) &lv_animimg_get_repeat_count, "i", "(lv.obj)" } },
|
||||||
{ "get_src_count", { (const void*) &lv_animimg_get_src_count, "i", "(lv.obj)" } },
|
{ "get_src_count", { (const void*) &lv_animimg_get_src_count, "i", "(lv.obj)" } },
|
||||||
|
|||||||
@ -1013,6 +1013,7 @@ const void ** lv_animimg_get_src(lv_obj_t * img)
|
|||||||
uint8_t lv_animimg_get_src_count(lv_obj_t * img)
|
uint8_t lv_animimg_get_src_count(lv_obj_t * img)
|
||||||
uint32_t lv_animimg_get_duration(lv_obj_t * img)
|
uint32_t lv_animimg_get_duration(lv_obj_t * img)
|
||||||
uint32_t lv_animimg_get_repeat_count(lv_obj_t * img)
|
uint32_t lv_animimg_get_repeat_count(lv_obj_t * img)
|
||||||
|
lv_anim_t * lv_animimg_get_anim(lv_obj_t * img)
|
||||||
|
|
||||||
// ../../lvgl/src/widgets/arc/lv_arc.h
|
// ../../lvgl/src/widgets/arc/lv_arc.h
|
||||||
lv_obj_t * lv_arc_create(lv_obj_t * parent)
|
lv_obj_t * lv_arc_create(lv_obj_t * parent)
|
||||||
@ -1061,7 +1062,7 @@ lv_obj_t * lv_button_create(lv_obj_t * parent)
|
|||||||
|
|
||||||
// ../../lvgl/src/widgets/buttonmatrix/lv_buttonmatrix.h
|
// ../../lvgl/src/widgets/buttonmatrix/lv_buttonmatrix.h
|
||||||
lv_obj_t * lv_buttonmatrix_create(lv_obj_t * parent)
|
lv_obj_t * lv_buttonmatrix_create(lv_obj_t * parent)
|
||||||
void lv_buttonmatrix_set_map(lv_obj_t * obj, const char * map[])
|
void lv_buttonmatrix_set_map(lv_obj_t * obj, const char * const map[])
|
||||||
void lv_buttonmatrix_set_ctrl_map(lv_obj_t * obj, const lv_buttonmatrix_ctrl_t ctrl_map[])
|
void lv_buttonmatrix_set_ctrl_map(lv_obj_t * obj, const lv_buttonmatrix_ctrl_t ctrl_map[])
|
||||||
void lv_buttonmatrix_set_selected_button(lv_obj_t * obj, uint32_t btn_id)
|
void lv_buttonmatrix_set_selected_button(lv_obj_t * obj, uint32_t btn_id)
|
||||||
void lv_buttonmatrix_set_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl)
|
void lv_buttonmatrix_set_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl)
|
||||||
@ -1070,7 +1071,7 @@ void lv_buttonmatrix_set_button_ctrl_all(lv_obj_t * obj, lv_buttonmatrix_ctrl_t
|
|||||||
void lv_buttonmatrix_clear_button_ctrl_all(lv_obj_t * obj, lv_buttonmatrix_ctrl_t ctrl)
|
void lv_buttonmatrix_clear_button_ctrl_all(lv_obj_t * obj, lv_buttonmatrix_ctrl_t ctrl)
|
||||||
void lv_buttonmatrix_set_button_width(lv_obj_t * obj, uint32_t btn_id, uint32_t width)
|
void lv_buttonmatrix_set_button_width(lv_obj_t * obj, uint32_t btn_id, uint32_t width)
|
||||||
void lv_buttonmatrix_set_one_checked(lv_obj_t * obj, bool en)
|
void lv_buttonmatrix_set_one_checked(lv_obj_t * obj, bool en)
|
||||||
const char ** lv_buttonmatrix_get_map(const lv_obj_t * obj)
|
const char * const * lv_buttonmatrix_get_map(const lv_obj_t * obj)
|
||||||
uint32_t lv_buttonmatrix_get_selected_button(const lv_obj_t * obj)
|
uint32_t lv_buttonmatrix_get_selected_button(const lv_obj_t * obj)
|
||||||
const char * lv_buttonmatrix_get_button_text(const lv_obj_t * obj, uint32_t btn_id)
|
const char * lv_buttonmatrix_get_button_text(const lv_obj_t * obj, uint32_t btn_id)
|
||||||
bool lv_buttonmatrix_has_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl)
|
bool lv_buttonmatrix_has_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl)
|
||||||
@ -1092,7 +1093,7 @@ lv_result_t lv_calendar_get_pressed_date(const lv_obj_t * calendar, lv_calendar_
|
|||||||
// ../../lvgl/src/widgets/calendar/lv_calendar_chinese.h
|
// ../../lvgl/src/widgets/calendar/lv_calendar_chinese.h
|
||||||
void lv_calendar_set_chinese_mode(lv_obj_t * obj, bool en)
|
void lv_calendar_set_chinese_mode(lv_obj_t * obj, bool en)
|
||||||
const char * lv_calendar_get_day_name(lv_calendar_date_t * gregorian)
|
const char * lv_calendar_get_day_name(lv_calendar_date_t * gregorian)
|
||||||
lv_calendar_chinese_t lv_calendar_gregorian_to_chinese(lv_calendar_date_t * gregorian)
|
void lv_calendar_gregorian_to_chinese(lv_calendar_date_t * gregorian_time, lv_calendar_chinese_t * chinese_time)
|
||||||
|
|
||||||
// ../../lvgl/src/widgets/calendar/lv_calendar_header_arrow.h
|
// ../../lvgl/src/widgets/calendar/lv_calendar_header_arrow.h
|
||||||
lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent)
|
lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent)
|
||||||
@ -1220,11 +1221,11 @@ lv_obj_t * lv_keyboard_create(lv_obj_t * parent)
|
|||||||
void lv_keyboard_set_textarea(lv_obj_t * kb, lv_obj_t * ta)
|
void lv_keyboard_set_textarea(lv_obj_t * kb, lv_obj_t * ta)
|
||||||
void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode)
|
void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode)
|
||||||
void lv_keyboard_set_popovers(lv_obj_t * kb, bool en)
|
void lv_keyboard_set_popovers(lv_obj_t * kb, bool en)
|
||||||
void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[], const lv_buttonmatrix_ctrl_t ctrl_map[])
|
void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * const map[], const lv_buttonmatrix_ctrl_t ctrl_map[])
|
||||||
lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * kb)
|
lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * kb)
|
||||||
lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * kb)
|
lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * kb)
|
||||||
bool lv_keyboard_get_popovers(const lv_obj_t * obj)
|
bool lv_keyboard_get_popovers(const lv_obj_t * obj)
|
||||||
const char ** lv_keyboard_get_map_array(const lv_obj_t * kb)
|
const char * const * lv_keyboard_get_map_array(const lv_obj_t * kb)
|
||||||
uint32_t lv_keyboard_get_selected_button(const lv_obj_t * obj)
|
uint32_t lv_keyboard_get_selected_button(const lv_obj_t * obj)
|
||||||
const char * lv_keyboard_get_button_text(const lv_obj_t * obj, uint32_t btn_id)
|
const char * lv_keyboard_get_button_text(const lv_obj_t * obj, uint32_t btn_id)
|
||||||
|
|
||||||
|
|||||||
@ -407,7 +407,7 @@ class type_mapper_class:
|
|||||||
"lv_roller_mode_t": "i",
|
"lv_roller_mode_t": "i",
|
||||||
"lv_table_cell_ctrl_t": "i",
|
"lv_table_cell_ctrl_t": "i",
|
||||||
|
|
||||||
"lv_calendar_chinese_t": "c",
|
# "lv_calendar_chinese_t": "c",
|
||||||
|
|
||||||
# adding ad-hoc colorwheel from LVGL8 to LVGL9
|
# adding ad-hoc colorwheel from LVGL8 to LVGL9
|
||||||
"lv_colorwheel_mode_t": "i",
|
"lv_colorwheel_mode_t": "i",
|
||||||
@ -459,6 +459,7 @@ class type_mapper_class:
|
|||||||
# "char **": "lv_str_arr", # treat as a simple pointer, decoding needs to be done at Berry level
|
# "char **": "lv_str_arr", # treat as a simple pointer, decoding needs to be done at Berry level
|
||||||
"constchar **": "c", # treat as a simple pointer, decoding needs to be done at Berry level
|
"constchar **": "c", # treat as a simple pointer, decoding needs to be done at Berry level
|
||||||
"void * []": "c", # treat as a simple pointer, decoding needs to be done at Berry level
|
"void * []": "c", # treat as a simple pointer, decoding needs to be done at Berry level
|
||||||
|
"constchar * *": "c",
|
||||||
|
|
||||||
# callbacks
|
# callbacks
|
||||||
"lv_group_focus_cb_t": "lv_group_focus_cb",
|
"lv_group_focus_cb_t": "lv_group_focus_cb",
|
||||||
|
|||||||
@ -136,7 +136,8 @@ class lvh_root
|
|||||||
return def () end
|
return def () end
|
||||||
end
|
end
|
||||||
def _delete()
|
def _delete()
|
||||||
# to be overriden
|
# remove from page
|
||||||
|
self._page.remove_obj(self.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
#################################################################################
|
#################################################################################
|
||||||
@ -668,8 +669,7 @@ class lvh_obj : lvh_root
|
|||||||
self.remove_text_rule()
|
self.remove_text_rule()
|
||||||
if (self._lv_label) self._lv_label.del() self._lv_label = nil end
|
if (self._lv_label) self._lv_label.del() self._lv_label = nil end
|
||||||
if (self._lv_obj) self._lv_obj.del() self._lv_obj = nil end
|
if (self._lv_obj) self._lv_obj.del() self._lv_obj = nil end
|
||||||
# remove from page
|
super(self)._delete()
|
||||||
self._page.remove_obj(self.id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#====================================================================
|
#====================================================================
|
||||||
@ -880,7 +880,7 @@ class lvh_obj : lvh_root
|
|||||||
def get_text_color(style_modifier)
|
def get_text_color(style_modifier)
|
||||||
return self._lv_obj.get_style_text_color(style_modifier)
|
return self._lv_obj.get_style_text_color(style_modifier)
|
||||||
end
|
end
|
||||||
def set_value_color(t) self.set_text_color(t) end
|
def set_value_color(t, style_modifier) self.set_text_color(t, style_modifier) end
|
||||||
def get_value_color() return self.get_value_color() end
|
def get_value_color() return self.get_value_color() end
|
||||||
|
|
||||||
#====================================================================
|
#====================================================================
|
||||||
@ -1869,6 +1869,7 @@ class lvh_scale_section : lvh_root
|
|||||||
self._style10 = nil
|
self._style10 = nil
|
||||||
self._style30.del()
|
self._style30.del()
|
||||||
self._style30 = nil
|
self._style30 = nil
|
||||||
|
super(self)._delete()
|
||||||
end
|
end
|
||||||
|
|
||||||
#- ------------------------------------------------------------#
|
#- ------------------------------------------------------------#
|
||||||
@ -2186,10 +2187,10 @@ class lvh_chart : lvh_obj
|
|||||||
end
|
end
|
||||||
|
|
||||||
def set_series1_color(color)
|
def set_series1_color(color)
|
||||||
self._lv_obj.set_series_color(self._ser1, color)
|
self._lv_obj.set_series_color(self._ser1, self.parse_color(color))
|
||||||
end
|
end
|
||||||
def set_series2_color(color)
|
def set_series2_color(color)
|
||||||
self._lv_obj.set_series_color(self._ser2, color)
|
self._lv_obj.set_series_color(self._ser2, self.parse_color(color))
|
||||||
end
|
end
|
||||||
def set_h_div_line_count(_h_div)
|
def set_h_div_line_count(_h_div)
|
||||||
self._h_div = _h_div
|
self._h_div = _h_div
|
||||||
@ -2365,14 +2366,43 @@ class lvh_page
|
|||||||
|
|
||||||
# create a global for this page of form p<page_number>, ex `p1`
|
# create a global for this page of form p<page_number>, ex `p1`
|
||||||
# create a global for the page attributes as p<page_number>b0, ex `p1b0`
|
# create a global for the page attributes as p<page_number>b0, ex `p1b0`
|
||||||
global.("p" + str(self._page_id)) = self
|
global.(f"p{self._page_id}") = self
|
||||||
global.("p" + str(self._page_id) + "b0") = obj_scr
|
global.(f"p{self._page_id}b0") = obj_scr
|
||||||
end
|
end
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
# General Setters and Getters
|
# General Setters and Getters
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
|
#- ------------------------------------------------------------#
|
||||||
|
# Internal utility functions
|
||||||
|
#
|
||||||
|
# Mapping of virtual attributes
|
||||||
|
#
|
||||||
|
#- ------------------------------------------------------------#
|
||||||
|
# `member` virtual getter
|
||||||
|
#- ------------------------------------------------------------#
|
||||||
|
def member(k)
|
||||||
|
import string
|
||||||
|
import introspect
|
||||||
|
|
||||||
|
if string.startswith(k, "set_") || string.startswith(k, "get_") return end
|
||||||
|
|
||||||
|
# if attribute name is in ignore list, abort
|
||||||
|
# if self._attr_ignore.find(k) != nil return end
|
||||||
|
# we don't need an ignore list for pages
|
||||||
|
|
||||||
|
# first check if there is a method named `get_X()`
|
||||||
|
var f = introspect.get(self, "get_" + k) # call self method
|
||||||
|
if type(f) == 'function'
|
||||||
|
# print(f">>>: getmember local method get_{k}")
|
||||||
|
return f(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
# fallback to exception if attribute unknown or not a function
|
||||||
|
return module("undefined")
|
||||||
|
end
|
||||||
|
|
||||||
#====================================================================
|
#====================================================================
|
||||||
# retrieve lvgl screen object for this page
|
# retrieve lvgl screen object for this page
|
||||||
#====================================================================
|
#====================================================================
|
||||||
@ -2413,6 +2443,44 @@ class lvh_page
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#====================================================================
|
||||||
|
# `delete` special attribute used to delete the object
|
||||||
|
#====================================================================
|
||||||
|
def get_clear()
|
||||||
|
self._clear()
|
||||||
|
return def () end
|
||||||
|
end
|
||||||
|
def _clear()
|
||||||
|
# iterate on all objects and try to delete
|
||||||
|
# we first get a copy of all ids so we can delete and continue iterating
|
||||||
|
# without fearing about an infinite loop
|
||||||
|
var ids = []
|
||||||
|
for id: self._obj_id.keys()
|
||||||
|
ids.push(id)
|
||||||
|
end
|
||||||
|
# we iterate until the array is empty
|
||||||
|
var idx = 0
|
||||||
|
while idx < size(ids)
|
||||||
|
var page_id = ids[idx]
|
||||||
|
if (page_id != 0) && self._obj_id.contains(page_id)
|
||||||
|
# first check if the id is still in the page - it could have been already removed if it's a sub-object
|
||||||
|
self._obj_id[page_id]._delete()
|
||||||
|
end
|
||||||
|
idx += 1
|
||||||
|
end
|
||||||
|
self._obj_id = {} # clear map
|
||||||
|
end
|
||||||
|
def get_delete()
|
||||||
|
self._delete()
|
||||||
|
return def () end
|
||||||
|
end
|
||||||
|
def _delete()
|
||||||
|
# remove from page, also change page if this is the current one
|
||||||
|
self._hm._remove_page(self._page_id)
|
||||||
|
# clear content
|
||||||
|
self._clear()
|
||||||
|
end
|
||||||
|
|
||||||
#====================================================================
|
#====================================================================
|
||||||
# `show` transition from one page to another
|
# `show` transition from one page to another
|
||||||
# duration: in ms, default 500 ms
|
# duration: in ms, default 500 ms
|
||||||
@ -2477,6 +2545,7 @@ class HASPmota
|
|||||||
# haspmota objects
|
# haspmota objects
|
||||||
var lvh_pages # (list of lvg_page) list of pages
|
var lvh_pages # (list of lvg_page) list of pages
|
||||||
var lvh_page_cur_idx # (int) current page index number
|
var lvh_page_cur_idx # (int) current page index number
|
||||||
|
var lvh_page_cur_idx_parsing # (int) index of the current page related to parsing JSONL, can be different from the displayed page
|
||||||
# regex patterns
|
# regex patterns
|
||||||
var re_page_target # compiled regex for action `p<number>`
|
var re_page_target # compiled regex for action `p<number>`
|
||||||
# specific event_cb handling for less memory usage since we are registering a lot of callbacks
|
# specific event_cb handling for less memory usage since we are registering a lot of callbacks
|
||||||
@ -2609,6 +2678,18 @@ class HASPmota
|
|||||||
def get_page_cur()
|
def get_page_cur()
|
||||||
return self.lvh_pages[self.lvh_page_cur_idx]
|
return self.lvh_pages[self.lvh_page_cur_idx]
|
||||||
end
|
end
|
||||||
|
#====================================================================
|
||||||
|
# return an array of all pages numbers
|
||||||
|
#====================================================================
|
||||||
|
def get_pages()
|
||||||
|
return self.pages_list_sorted(nil)
|
||||||
|
end
|
||||||
|
#====================================================================
|
||||||
|
# return the current page being parsed with JSONL as `lvh_page` object
|
||||||
|
#====================================================================
|
||||||
|
def get_page_cur_parsing()
|
||||||
|
return self.lvh_pages[self.lvh_page_cur_idx_parsing]
|
||||||
|
end
|
||||||
|
|
||||||
#====================================================================
|
#====================================================================
|
||||||
# load JSONL template
|
# load JSONL template
|
||||||
@ -2633,12 +2714,12 @@ class HASPmota
|
|||||||
if tasmota.loglevel(4)
|
if tasmota.loglevel(4)
|
||||||
tasmota.log(f"HSP: parsing line '{jsonl[0]}'", 4)
|
tasmota.log(f"HSP: parsing line '{jsonl[0]}'", 4)
|
||||||
end
|
end
|
||||||
self.parse_page(jline) # parse page first to create any page related objects, may change self.lvh_page_cur_idx
|
self.parse_page(jline) # parse page first to create any page related objects, may change self.lvh_page_cur_idx_parsing
|
||||||
# objects are created in the current page
|
# objects are created in the current page
|
||||||
if (self.lvh_pages == nil)
|
if (self.lvh_pages == nil)
|
||||||
raise "value_error", "no page 'id' defined"
|
raise "value_error", "no page 'id' defined"
|
||||||
end
|
end
|
||||||
self.parse_obj(jline, self.lvh_pages[self.lvh_page_cur_idx]) # then parse object within this page
|
self.parse_obj(jline, self.lvh_pages[self.lvh_page_cur_idx_parsing]) # then parse object within this page
|
||||||
else
|
else
|
||||||
# check if it's invalid json
|
# check if it's invalid json
|
||||||
if size(string.tr(jsonl[0], " \t", "")) > 0
|
if size(string.tr(jsonl[0], " \t", "")) > 0
|
||||||
@ -2669,7 +2750,7 @@ class HASPmota
|
|||||||
var jline = json.load(j)
|
var jline = json.load(j)
|
||||||
|
|
||||||
if type(jline) == 'instance'
|
if type(jline) == 'instance'
|
||||||
self.parse_page(jline) # parse page first to create any page related objects, may change self.lvh_page_cur_idx
|
self.parse_page(jline) # parse page first to create any page related objects, may change self.lvh_page_cur_idx_parsing
|
||||||
# objects are created in the current page
|
# objects are created in the current page
|
||||||
self.parse_obj(jline, self.lvh_pages[self.lvh_page_cur_idx]) # then parse object within this page
|
self.parse_obj(jline, self.lvh_pages[self.lvh_page_cur_idx]) # then parse object within this page
|
||||||
else
|
else
|
||||||
@ -2757,37 +2838,60 @@ class HASPmota
|
|||||||
# Execute a page changing action from string `action`
|
# Execute a page changing action from string `action`
|
||||||
#
|
#
|
||||||
# Arg1 `action` can be `prev`, `next`, `back` or `p<number>`
|
# Arg1 `action` can be `prev`, `next`, `back` or `p<number>`
|
||||||
# Returns: nil
|
# of `delete` if we are deleting the current page
|
||||||
|
# duration: in ms, default 500 ms
|
||||||
|
# anim: -1 right to left, 1 left to right (default), `nil` auto, 0 none
|
||||||
|
# Returns: the target page object if changed, or `nil` if still on same page
|
||||||
#====================================================================
|
#====================================================================
|
||||||
def page_show(action)
|
def page_show(action, anim, duration)
|
||||||
|
# resolve between page numbers
|
||||||
|
# p1 is either a number or nil (stored value)
|
||||||
|
# p2 is the default value
|
||||||
|
# l is the list of page ids
|
||||||
|
def to_page_resolve(p1, p_def, l)
|
||||||
|
if (p1 != nil) && (l.find(p1) != nil)
|
||||||
|
return p1
|
||||||
|
else
|
||||||
|
return p_def
|
||||||
|
end
|
||||||
|
end
|
||||||
# action can be `prev`, `next`, `back`, or `p<number>` like `p1`
|
# action can be `prev`, `next`, `back`, or `p<number>` like `p1`
|
||||||
var to_page = nil
|
var to_page = nil
|
||||||
var cur_page = self.lvh_pages[self.lvh_page_cur_idx]
|
var cur_page = self.get_page_cur()
|
||||||
var sorted_pages_list = self.pages_list_sorted(self.lvh_page_cur_idx)
|
var sorted_pages_list = self.pages_list_sorted(self.lvh_page_cur_idx)
|
||||||
if size(sorted_pages_list) <= 1 return end # if only 1 page, do nothing
|
|
||||||
|
if size(sorted_pages_list) <= 1 # if only 1 page, do nothing
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
# handle prev/next/back values
|
# handle prev/next/back values
|
||||||
# get the corresponding value from page object,
|
# get the corresponding value from page object,
|
||||||
# if absent, revert to next page, previous page and page 1
|
# if absent, revert to next page, previous page and page 1
|
||||||
# print("sorted_pages_list",sorted_pages_list)
|
# print("sorted_pages_list",sorted_pages_list)
|
||||||
if action == 'prev'
|
if action == 'prev'
|
||||||
to_page = int(cur_page.prev)
|
to_page = to_page_resolve(int(cur_page.prev), sorted_pages_list[-1], sorted_pages_list)
|
||||||
if to_page == nil to_page = sorted_pages_list[-1] end # if no prev, take the previous page
|
|
||||||
elif action == 'next'
|
elif action == 'next'
|
||||||
to_page = int(cur_page.next)
|
to_page = to_page_resolve(int(cur_page.next), sorted_pages_list[1], sorted_pages_list)
|
||||||
if to_page == nil to_page = sorted_pages_list[1] end # if no next, take the next page
|
|
||||||
elif action == 'back'
|
elif action == 'back'
|
||||||
to_page = int(cur_page.back)
|
to_page = to_page_resolve(int(cur_page.back), self.pages_list_sorted(nil)[0], sorted_pages_list)
|
||||||
if to_page == nil # if no back, take first page
|
elif action == 'delete'
|
||||||
to_page = self.pages_list_sorted(nil)[0]
|
to_page = to_page_resolve(int(cur_page.back), self.pages_list_sorted(nil)[0], sorted_pages_list)
|
||||||
end
|
if (to_page == cur_page.id())
|
||||||
|
to_page = to_page_resolve(int(cur_page.next), sorted_pages_list[1], sorted_pages_list)
|
||||||
|
end
|
||||||
elif self.re_page_target.match(action)
|
elif self.re_page_target.match(action)
|
||||||
# action is supposed to be `p<number>` format
|
# action is supposed to be `p<number>` format
|
||||||
to_page = int(action[1..-1]) # just skip first char and convert the rest to a string
|
to_page = to_page_resolve(int(action[1..-1]), nil #-default to nil-#, sorted_pages_list)
|
||||||
end
|
end
|
||||||
|
|
||||||
# print("to_page=",to_page)
|
# print(f"{action=} {to_page=}")
|
||||||
if to_page != nil && to_page > 0 # we have a target
|
if (to_page != nil) && (to_page > 0) # we have a target
|
||||||
self.lvh_pages[to_page].show() # switch to the target page
|
var to_page_obj = self.lvh_pages[to_page]
|
||||||
|
# print(f"{to_page_obj.id()=}")
|
||||||
|
if (to_page_obj != nil)
|
||||||
|
to_page_obj.show(anim, duration)
|
||||||
|
end
|
||||||
|
return to_page_obj
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2800,7 +2904,11 @@ class HASPmota
|
|||||||
def parse_page(jline)
|
def parse_page(jline)
|
||||||
if jline.has("page") && type(jline["page"]) == 'int'
|
if jline.has("page") && type(jline["page"]) == 'int'
|
||||||
var page = int(jline["page"])
|
var page = int(jline["page"])
|
||||||
self.lvh_page_cur_idx = page # change current page
|
# print(f">>> parsing page {page}")
|
||||||
|
self.lvh_page_cur_idx_parsing = page # change current page
|
||||||
|
if (self.lvh_page_cur_idx == nil) # also set current page if we haven't any yet
|
||||||
|
self.lvh_page_cur_idx = page
|
||||||
|
end
|
||||||
|
|
||||||
# create the page object if it doesn't exist already
|
# create the page object if it doesn't exist already
|
||||||
if !self.lvh_pages.contains(page)
|
if !self.lvh_pages.contains(page)
|
||||||
@ -2810,7 +2918,7 @@ class HASPmota
|
|||||||
|
|
||||||
# check if there is "id":0
|
# check if there is "id":0
|
||||||
if jline.find("id") == 0
|
if jline.find("id") == 0
|
||||||
var lvh_page_cur = self.get_page_cur()
|
var lvh_page_cur = self.get_page_cur_parsing()
|
||||||
lvh_page_cur.prev = int(jline.find("prev", nil))
|
lvh_page_cur.prev = int(jline.find("prev", nil))
|
||||||
lvh_page_cur.next = int(jline.find("next", nil))
|
lvh_page_cur.next = int(jline.find("next", nil))
|
||||||
lvh_page_cur.back = int(jline.find("back", nil))
|
lvh_page_cur.back = int(jline.find("back", nil))
|
||||||
@ -2818,6 +2926,36 @@ class HASPmota
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#====================================================================
|
||||||
|
# Remove page by id
|
||||||
|
#
|
||||||
|
# Should not be called directly. Indirectly called by `p<x>.delete`
|
||||||
|
#
|
||||||
|
# Only removes reference to the page at root level
|
||||||
|
# Change the active page if needed
|
||||||
|
#====================================================================
|
||||||
|
def _remove_page(page_id)
|
||||||
|
# check if we remove the active page
|
||||||
|
var cur_page_id = self.get_page_cur().id()
|
||||||
|
if (page_id == cur_page_id)
|
||||||
|
# if we try to delete the current page, move do main page
|
||||||
|
var to_page_obj = self.page_show("delete", 0, 0 #-no animation-#) # get the target page as result
|
||||||
|
if (to_page_obj == nil) # we didn't change page
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# also update lvh_page_cur_idx_parsing, if we removed the current parsing page
|
||||||
|
if (self.lvh_page_cur_idx_parsing == page_id)
|
||||||
|
self.lvh_page_cur_idx_parsing = self.lvh_page_cur_idx
|
||||||
|
end
|
||||||
|
# remove object from page object
|
||||||
|
if self.lvh_pages.contains(page_id)
|
||||||
|
self.lvh_pages.remove(page_id)
|
||||||
|
end
|
||||||
|
# remove global for page
|
||||||
|
global.(f"p{page_id}") = nil
|
||||||
|
end
|
||||||
|
|
||||||
#====================================================================
|
#====================================================================
|
||||||
# Event CB handling
|
# Event CB handling
|
||||||
#====================================================================
|
#====================================================================
|
||||||
@ -2856,65 +2994,70 @@ class HASPmota
|
|||||||
|
|
||||||
#====================================================================
|
#====================================================================
|
||||||
# Parse single object
|
# Parse single object
|
||||||
|
#
|
||||||
|
# The object may be pre-existing or brand new
|
||||||
#====================================================================
|
#====================================================================
|
||||||
def parse_obj(jline, page)
|
def parse_obj(jline, page)
|
||||||
import global
|
import global
|
||||||
import introspect
|
import introspect
|
||||||
|
|
||||||
var obj_id = int(jline.find("id")) # id number or nil
|
var obj_id = int(jline.find("id")) # id number or nil
|
||||||
var obj_type = str(jline.find("obj")) # obj class or nil
|
var obj_type = jline.find("obj") # obj class or nil
|
||||||
var obj_lvh # lvgl object created
|
obj_type = (obj_type != nil) ? str(obj_type) : nil
|
||||||
var lvh_page_cur = self.get_page_cur() # current page object
|
var lvh_page_cur = self.get_page_cur_parsing() # current page object, cannot be nil
|
||||||
|
|
||||||
# first run any Berry code embedded
|
# Step 1. Check the id for valid range
|
||||||
var berry_run = str(jline.find("berry_run"))
|
# 'obj_id' must be between 1 and 254
|
||||||
var func_compiled
|
if (obj_id != nil) && (obj_id < 0 || obj_id > 254)
|
||||||
if berry_run != "nil"
|
if (obj_id != 0) || (obj_type == nil)
|
||||||
try
|
# if `obj_id` is not `nil` and not `0`, it must have `obj_type` not set to `nil`
|
||||||
func_compiled = compile(berry_run)
|
print(f"HSP: invalid 'id': {obj_id} for 'obj': {obj_type}")
|
||||||
except .. as e,m
|
return
|
||||||
print(format("HSP: unable to compile berry code \"%s\" - '%s' - %s", berry_run, e, m))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# if line contains botn 'obj' and 'id', create the object
|
# Step 2. Check if the p<>b<> object already exists
|
||||||
if obj_type != "nil" && obj_id != nil
|
# `prev_obj` contains the pre-existing object, or `nil` if we create a new object
|
||||||
# 'obj_id' must be between 1 and 254
|
var obj_lvh = lvh_page_cur.get_obj(obj_id) # get reference of object or `nil` if new object
|
||||||
if obj_id < 1 || obj_id > 254
|
|
||||||
print("HSP: invalid 'id': " + str(obj_id) + " for 'obj':" + obj_type)
|
# Step 3. Create object instance if required
|
||||||
return
|
if (obj_type != nil) && (obj_id != nil) && (obj_lvh == nil)
|
||||||
end
|
|
||||||
|
# Step 3.a. extract the LVGL parent object to create the object in the appropriate lvgl screen
|
||||||
|
# Result in `parent_lvgl`
|
||||||
|
|
||||||
# extract haspmota class, prefix with `lvh_`. Ex: `btn` becomes `lvh_btn`
|
# extract haspmota class, prefix with `lvh_`. Ex: `btn` becomes `lvh_btn`
|
||||||
# extract parent
|
var parent_id = int(jline.find("parentid")) # id of parent object, or `nil`
|
||||||
var parent_lvgl
|
var parent_obj # parent HASPmota object
|
||||||
var parent_id = int(jline.find("parentid"))
|
var parent_lvgl # lvgl object of parent object
|
||||||
|
|
||||||
var parent_obj
|
|
||||||
if parent_id != nil
|
if parent_id != nil
|
||||||
parent_obj = lvh_page_cur.get_obj(parent_id) # get parent object
|
parent_obj = lvh_page_cur.get_obj(parent_id) # get parent object
|
||||||
if parent_obj != nil parent_lvgl = parent_obj._lv_obj end # parent
|
if parent_obj != nil
|
||||||
|
parent_lvgl = parent_obj._lv_obj
|
||||||
|
end # parent
|
||||||
end
|
end
|
||||||
if parent_lvgl == nil
|
if parent_lvgl == nil
|
||||||
parent_lvgl = lvh_page_cur.get_scr() # if not parent, use the current page screen
|
parent_lvgl = lvh_page_cur.get_scr() # if not parent, use the current page screen
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Step 3.b. Get the HASPmota class object for the `obj` class
|
||||||
# check if a class with the requested name exists
|
# check if a class with the requested name exists
|
||||||
# first look for a class with name `lvh_<name>` exists
|
# first look for a class with name `lvh_<name>` exists
|
||||||
var obj_class = introspect.get(self, "lvh_" + obj_type)
|
var obj_class = introspect.get(self, "lvh_" + obj_type)
|
||||||
var lv_instance = nil # allows to pre-instanciate the object
|
var lv_instance # allows to pre-instanciate the object
|
||||||
|
|
||||||
# there is no lvh_X class, try to load the class name from the global namespace
|
# Step 3.c. if no native `lvh_<obj>` is found, try the class name from the global namespace
|
||||||
if obj_class == nil
|
if obj_class == nil
|
||||||
# if not found, check if a LVGL class with name `lv_<name>` exists
|
# if not found, check if a LVGL class with name `lv_<name>` exists
|
||||||
var lv_cl = introspect.get(global, obj_type)
|
var lv_cl = introspect.get(global, obj_type)
|
||||||
if lv_cl != nil && type(lv_cl) == 'class'
|
if (lv_cl != nil) && (type(lv_cl) == 'class')
|
||||||
lv_instance = lv_cl(parent_lvgl)
|
lv_instance = lv_cl(parent_lvgl)
|
||||||
obj_class = self.lvh_obj # use the basic lvh_obj component to encapsulate
|
obj_class = self.lvh_obj # use the basic lvh_obj component to encapsulate
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# still not found, try to load a module with the name of the class
|
# Step 3.d. if not found, try to load a module with the name of the class
|
||||||
if obj_class == nil
|
if obj_class == nil
|
||||||
var lv_cl = introspect.module(obj_type)
|
var lv_cl = introspect.module(obj_type)
|
||||||
if lv_cl != nil && type(lv_cl) == 'class'
|
if lv_cl != nil && type(lv_cl) == 'class'
|
||||||
@ -2923,18 +3066,55 @@ class HASPmota
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Step 3.e. if none found, raise an error and abort
|
||||||
if obj_class == nil
|
if obj_class == nil
|
||||||
print("HSP: Cannot find object of type " + str(obj_type))
|
print(f"HSP: Cannot find object of type {obj_type}")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
# instanciate the object, passing the lvgl screen as parent object
|
# Step 3.f. instanciate the object, passing the lvgl screen as parent object
|
||||||
obj_lvh = obj_class(parent_lvgl, page, jline, lv_instance, parent_obj)
|
obj_lvh = obj_class(parent_lvgl, page, jline, lv_instance, parent_obj)
|
||||||
|
|
||||||
# add object to page object
|
# Step 3.g. Add object to page object
|
||||||
lvh_page_cur.add_obj(obj_id, obj_lvh)
|
lvh_page_cur.add_obj(obj_id, obj_lvh)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Step 4. if "id" is 0, get the screen object
|
||||||
|
if obj_id == 0
|
||||||
|
if (obj_type != nil)
|
||||||
|
print(f"HSP: cannot specify 'obj':'{obj_type}' for 'id':0")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
obj_lvh = self.get_page_cur_parsing().get_obj(0) # get object id '0'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Step 5. apply attributes
|
||||||
|
# set attributes
|
||||||
|
# try every attribute, if not supported it is silently ignored
|
||||||
|
if (obj_lvh != nil)
|
||||||
|
for k:jline.keys()
|
||||||
|
obj_lvh.(k) = jline[k]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Step 6. apply post-config
|
||||||
|
# finally call 'post_config()' when all attributes are set, which gives an opportunity to clean or refresh
|
||||||
|
if (obj_lvh != nil)
|
||||||
|
obj_lvh.post_config()
|
||||||
|
end
|
||||||
|
|
||||||
|
# Step 7. run any Berry code embedded
|
||||||
|
# `func_compiled` contains compiled code, that will be run once the object is complete, or `nil` if no code
|
||||||
|
# `berry_run` contains the actual source code, used only for logging
|
||||||
|
var func_compiled
|
||||||
|
var berry_run = str(jline.find("berry_run"))
|
||||||
|
if berry_run != "nil"
|
||||||
|
try
|
||||||
|
func_compiled = compile(berry_run)
|
||||||
|
except .. as e,m
|
||||||
|
print(format("HSP: unable to compile berry code \"%s\" - '%s' - %s", berry_run, e, m))
|
||||||
|
end
|
||||||
|
end
|
||||||
if func_compiled != nil
|
if func_compiled != nil
|
||||||
try
|
try
|
||||||
# run the compiled code once
|
# run the compiled code once
|
||||||
@ -2947,26 +3127,6 @@ class HASPmota
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if obj_id == nil return end # if no object id, ignore line
|
|
||||||
if obj_id == 0 && obj_type != "nil"
|
|
||||||
print("HSP: cannot specify 'obj' for 'id':0")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# if id==0, retrieve the 'scr' object of the current page
|
|
||||||
if obj_id == 0
|
|
||||||
obj_lvh = self.get_page_cur().get_obj(0) # get object id '0'
|
|
||||||
end
|
|
||||||
|
|
||||||
# set attributes
|
|
||||||
# try every attribute, if not supported it is silently ignored
|
|
||||||
for k:jline.keys()
|
|
||||||
# introspect.set(obj, k, jline[k])
|
|
||||||
obj_lvh.(k) = jline[k]
|
|
||||||
end
|
|
||||||
|
|
||||||
# finally call 'post_config()' when all attributes are set, which gives an opportunity to clean or refresh
|
|
||||||
obj_lvh.post_config()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
haspmota.HASPmota = HASPmota
|
haspmota.HASPmota = HASPmota
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "lvgl",
|
"name": "lvgl",
|
||||||
"version": "9.2.0",
|
"version": "9.2.2",
|
||||||
"keywords": "graphics, gui, embedded, tft, lvgl",
|
"keywords": "graphics, gui, embedded, tft, lvgl",
|
||||||
"description": "Graphics library to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint. It offers anti-aliasing, opacity, and animations using only one frame buffer.",
|
"description": "Graphics library to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint. It offers anti-aliasing, opacity, and animations using only one frame buffer.",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name=lvgl
|
name=lvgl
|
||||||
version=9.2.0
|
version=9.2.2
|
||||||
author=kisvegabor
|
author=kisvegabor
|
||||||
maintainer=kisvegabor,embeddedt,pete-pjb
|
maintainer=kisvegabor,embeddedt,pete-pjb
|
||||||
sentence=Full-featured Graphics Library for Embedded Systems
|
sentence=Full-featured Graphics Library for Embedded Systems
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file lv_conf.h
|
* @file lv_conf.h
|
||||||
* Configuration file for v9.2.0
|
* Configuration file for v9.2.2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -95,6 +95,14 @@
|
|||||||
#if LV_USE_OS == LV_OS_CUSTOM
|
#if LV_USE_OS == LV_OS_CUSTOM
|
||||||
#define LV_OS_CUSTOM_INCLUDE <stdint.h>
|
#define LV_OS_CUSTOM_INCLUDE <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
#if LV_USE_OS == LV_OS_FREERTOS
|
||||||
|
/*
|
||||||
|
* Unblocking an RTOS task with a direct notification is 45% faster and uses less RAM
|
||||||
|
* than unblocking a task using an intermediary object such as a binary semaphore.
|
||||||
|
* RTOS task notifications can only be used when there is only one task that can be the recipient of the event.
|
||||||
|
*/
|
||||||
|
#define LV_USE_FREERTOS_TASK_NOTIFY 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/*========================
|
/*========================
|
||||||
* RENDERING CONFIGURATION
|
* RENDERING CONFIGURATION
|
||||||
@ -205,10 +213,16 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Use NXP's PXP on iMX RTxxx platforms. */
|
/* Use NXP's PXP on iMX RTxxx platforms. */
|
||||||
#define LV_USE_DRAW_PXP 0
|
#define LV_USE_PXP 0
|
||||||
|
|
||||||
#if LV_USE_DRAW_PXP
|
#if LV_USE_PXP
|
||||||
#if LV_USE_OS
|
/* Use PXP for drawing.*/
|
||||||
|
#define LV_USE_DRAW_PXP 1
|
||||||
|
|
||||||
|
/* Use PXP to rotate display.*/
|
||||||
|
#define LV_USE_ROTATE_PXP 0
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_PXP && LV_USE_OS
|
||||||
/* Use additional draw thread for PXP processing.*/
|
/* Use additional draw thread for PXP processing.*/
|
||||||
#define LV_USE_PXP_DRAW_THREAD 1
|
#define LV_USE_PXP_DRAW_THREAD 1
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#define LVGL_VERSION_MAJOR 9
|
#define LVGL_VERSION_MAJOR 9
|
||||||
#define LVGL_VERSION_MINOR 2
|
#define LVGL_VERSION_MINOR 2
|
||||||
#define LVGL_VERSION_PATCH 0
|
#define LVGL_VERSION_PATCH 2
|
||||||
#define LVGL_VERSION_INFO ""
|
#define LVGL_VERSION_INFO ""
|
||||||
|
|
||||||
#endif /* LVGL_VERSION_H */
|
#endif /* LVGL_VERSION_H */
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user